Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: src/objects.cc

Issue 15691007: Make Object.freeze fast (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4489 matching lines...) Expand 10 before | Expand all | Expand 10 after
4500 4500
4501 4501
4502 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { 4502 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
4503 if (HasFastProperties()) return this; 4503 if (HasFastProperties()) return this;
4504 ASSERT(!IsGlobalObject()); 4504 ASSERT(!IsGlobalObject());
4505 return property_dictionary()-> 4505 return property_dictionary()->
4506 TransformPropertiesToFastFor(this, unused_property_fields); 4506 TransformPropertiesToFastFor(this, unused_property_fields);
4507 } 4507 }
4508 4508
4509 4509
4510 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary(
4511 Isolate* isolate,
4512 FixedArrayBase* array,
4513 int length,
4514 SeededNumberDictionary* dictionary) {
4515 Heap* heap = isolate->heap();
4516 bool has_double_elements = array->IsFixedDoubleArray();
4517 for (int i = 0; i < length; i++) {
4518 Object* value = NULL;
4519 if (has_double_elements) {
4520 FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
4521 if (double_array->is_the_hole(i)) {
4522 value = isolate->heap()->the_hole_value();
4523 } else {
4524 // Objects must be allocated in the old object space, since the
4525 // overall number of HeapNumbers needed for the conversion might
4526 // exceed the capacity of new space, and we would fail repeatedly
4527 // trying to convert the FixedDoubleArray.
4528 MaybeObject* maybe_value_object =
4529 heap->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
4530 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
4531 }
4532 } else {
4533 value = FixedArray::cast(array)->get(i);
4534 }
4535 if (!value->IsTheHole()) {
4536 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4537 MaybeObject* maybe_result =
4538 dictionary->AddNumberEntry(i, value, details);
4539 if (!maybe_result->To(&dictionary)) return maybe_result;
4540 }
4541 }
4542 return dictionary;
4543 }
4544
4545
4510 Handle<SeededNumberDictionary> JSObject::NormalizeElements( 4546 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4511 Handle<JSObject> object) { 4547 Handle<JSObject> object) {
4512 CALL_HEAP_FUNCTION(object->GetIsolate(), 4548 CALL_HEAP_FUNCTION(object->GetIsolate(),
4513 object->NormalizeElements(), 4549 object->NormalizeElements(),
4514 SeededNumberDictionary); 4550 SeededNumberDictionary);
4515 } 4551 }
4516 4552
4517 4553
4518 MaybeObject* JSObject::NormalizeElements() { 4554 MaybeObject* JSObject::NormalizeElements() {
4519 ASSERT(!HasExternalArrayElements()); 4555 ASSERT(!HasExternalArrayElements());
(...skipping 11 matching lines...) Expand all
4531 ASSERT(HasFastSmiOrObjectElements() || 4567 ASSERT(HasFastSmiOrObjectElements() ||
4532 HasFastDoubleElements() || 4568 HasFastDoubleElements() ||
4533 HasFastArgumentsElements()); 4569 HasFastArgumentsElements());
4534 // Compute the effective length and allocate a new backing store. 4570 // Compute the effective length and allocate a new backing store.
4535 int length = IsJSArray() 4571 int length = IsJSArray()
4536 ? Smi::cast(JSArray::cast(this)->length())->value() 4572 ? Smi::cast(JSArray::cast(this)->length())->value()
4537 : array->length(); 4573 : array->length();
4538 int old_capacity = 0; 4574 int old_capacity = 0;
4539 int used_elements = 0; 4575 int used_elements = 0;
4540 GetElementsCapacityAndUsage(&old_capacity, &used_elements); 4576 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4541 SeededNumberDictionary* dictionary = NULL; 4577 SeededNumberDictionary* dictionary;
4542 { Object* object; 4578 MaybeObject* maybe_dictionary =
4543 MaybeObject* maybe = 4579 SeededNumberDictionary::Allocate(GetHeap(), used_elements);
4544 SeededNumberDictionary::Allocate(GetHeap(), used_elements); 4580 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4545 if (!maybe->ToObject(&object)) return maybe;
4546 dictionary = SeededNumberDictionary::cast(object);
4547 }
4548 4581
4549 // Copy the elements to the new backing store. 4582 maybe_dictionary = CopyFastElementsToDictionary(
4550 bool has_double_elements = array->IsFixedDoubleArray(); 4583 GetIsolate(), array, length, dictionary);
4551 for (int i = 0; i < length; i++) { 4584 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4552 Object* value = NULL;
4553 if (has_double_elements) {
4554 FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
4555 if (double_array->is_the_hole(i)) {
4556 value = GetIsolate()->heap()->the_hole_value();
4557 } else {
4558 // Objects must be allocated in the old object space, since the
4559 // overall number of HeapNumbers needed for the conversion might
4560 // exceed the capacity of new space, and we would fail repeatedly
4561 // trying to convert the FixedDoubleArray.
4562 MaybeObject* maybe_value_object =
4563 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
4564 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
4565 }
4566 } else {
4567 ASSERT(old_map->has_fast_smi_or_object_elements());
4568 value = FixedArray::cast(array)->get(i);
4569 }
4570 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4571 if (!value->IsTheHole()) {
4572 Object* result;
4573 MaybeObject* maybe_result =
4574 dictionary->AddNumberEntry(i, value, details);
4575 if (!maybe_result->ToObject(&result)) return maybe_result;
4576 dictionary = SeededNumberDictionary::cast(result);
4577 }
4578 }
4579 4585
4580 // Switch to using the dictionary as the backing storage for elements. 4586 // Switch to using the dictionary as the backing storage for elements.
4581 if (is_arguments) { 4587 if (is_arguments) {
4582 FixedArray::cast(elements())->set(1, dictionary); 4588 FixedArray::cast(elements())->set(1, dictionary);
4583 } else { 4589 } else {
4584 // Set the new map first to satify the elements type assert in 4590 // Set the new map first to satify the elements type assert in
4585 // set_elements(). 4591 // set_elements().
4586 Object* new_map; 4592 Map* new_map;
4587 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), 4593 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
4588 DICTIONARY_ELEMENTS); 4594 DICTIONARY_ELEMENTS);
4589 if (!maybe->ToObject(&new_map)) return maybe; 4595 if (!maybe->To(&new_map)) return maybe;
4590 set_map(Map::cast(new_map)); 4596 set_map(new_map);
4591 set_elements(dictionary); 4597 set_elements(dictionary);
4592 } 4598 }
4593 4599
4594 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> 4600 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
4595 Increment(); 4601 Increment();
4596 4602
4597 #ifdef DEBUG 4603 #ifdef DEBUG
4598 if (FLAG_trace_normalization) { 4604 if (FLAG_trace_normalization) {
4599 PrintF("Object elements have been normalized:\n"); 4605 PrintF("Object elements have been normalized:\n");
4600 Print(); 4606 Print();
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after
5324 SeededNumberDictionary* dictionary = NULL; 5330 SeededNumberDictionary* dictionary = NULL;
5325 { MaybeObject* maybe = NormalizeElements(); 5331 { MaybeObject* maybe = NormalizeElements();
5326 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; 5332 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
5327 } 5333 }
5328 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 5334 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
5329 // Make sure that we never go back to fast case. 5335 // Make sure that we never go back to fast case.
5330 dictionary->set_requires_slow_elements(); 5336 dictionary->set_requires_slow_elements();
5331 5337
5332 // Do a map transition, other objects with this map may still 5338 // Do a map transition, other objects with this map may still
5333 // be extensible. 5339 // be extensible.
5340 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5334 Map* new_map; 5341 Map* new_map;
5335 MaybeObject* maybe = map()->Copy(); 5342 MaybeObject* maybe = map()->Copy();
5336 if (!maybe->To(&new_map)) return maybe; 5343 if (!maybe->To(&new_map)) return maybe;
5337 5344
5338 new_map->set_is_extensible(false); 5345 new_map->set_is_extensible(false);
5339 set_map(new_map); 5346 set_map(new_map);
5340 ASSERT(!map()->is_extensible()); 5347 ASSERT(!map()->is_extensible());
5341 return new_map; 5348 return new_map;
5342 } 5349 }
5343 5350
5344 5351
5352 template<typename Dictionary>
5353 static void FreezeDictionary(Dictionary* dictionary) {
5354 int capacity = dictionary->Capacity();
5355 for (int i = 0; i < capacity; i++) {
5356 Object* k = dictionary->KeyAt(i);
5357 if (dictionary->IsKey(k)) {
5358 PropertyDetails details = dictionary->DetailsAt(i);
5359 int attrs = DONT_DELETE;
5360 // READ_ONLY is an invalid attribute for JS setters/getters.
5361 if (details.type() != CALLBACKS ||
5362 !dictionary->ValueAt(i)->IsAccessorPair()) {
5363 attrs |= READ_ONLY;
5364 }
5365 details = details.CopyAddAttributes(
5366 static_cast<PropertyAttributes>(attrs));
5367 dictionary->DetailsAtPut(i, details);
5368 }
5369 }
5370 }
5371
5372
5373 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) {
5374 // Freezing non-strict arguments should be handled elsewhere.
5375 ASSERT(!HasNonStrictArgumentsElements());
5376
5377 Heap* heap = isolate->heap();
5378
5379 if (map()->is_frozen()) return this;
5380
5381 if (IsAccessCheckNeeded() &&
5382 !isolate->MayNamedAccess(this,
5383 heap->undefined_value(),
5384 v8::ACCESS_KEYS)) {
5385 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
5386 return heap->false_value();
5387 }
5388
5389 if (IsJSGlobalProxy()) {
5390 Object* proto = GetPrototype();
5391 if (proto->IsNull()) return this;
5392 ASSERT(proto->IsJSGlobalObject());
5393 return JSObject::cast(proto)->Freeze(isolate);
5394 }
5395
5396 // It's not possible to freeze objects with external array elements
5397 if (HasExternalArrayElements()) {
5398 HandleScope scope(isolate);
5399 Handle<Object> object(this, isolate);
5400 Handle<Object> error =
5401 isolate->factory()->NewTypeError(
5402 "cant_prevent_ext_external_array_elements",
5403 HandleVector(&object, 1));
5404 return isolate->Throw(*error);
5405 }
5406
5407 SeededNumberDictionary* new_element_dictionary = NULL;
5408 if (!elements()->IsDictionary()) {
5409 int length = IsJSArray()
5410 ? Smi::cast(JSArray::cast(this)->length())->value()
5411 : elements()->length();
5412 if (length > 0) {
5413 int capacity = 0;
5414 int used = 0;
5415 GetElementsCapacityAndUsage(&capacity, &used);
5416 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used);
5417 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
5418
5419 // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5420 // unnecessary transitions.
5421 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length,
5422 new_element_dictionary);
5423 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
5424 } else {
5425 // No existing elements, use a pre-allocated empty backing store
5426 new_element_dictionary = heap->empty_slow_element_dictionary();
5427 }
5428 }
5429
5430 LookupResult result(isolate);
5431 map()->LookupTransition(this, heap->frozen_symbol(), &result);
5432 if (result.IsTransition()) {
5433 Map* transition_map = result.GetTransitionTarget();
5434 ASSERT(transition_map->has_dictionary_elements());
5435 ASSERT(transition_map->is_frozen());
5436 ASSERT(!transition_map->is_extensible());
5437 set_map(transition_map);
5438 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) {
5439 // Create a new descriptor array with fully-frozen properties
5440 int num_descriptors = map()->NumberOfOwnDescriptors();
5441 DescriptorArray* new_descriptors;
5442 MaybeObject* maybe_descriptors =
5443 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors,
5444 FROZEN);
5445 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5446
5447 Map* new_map;
5448 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(
5449 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol());
5450 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5451 new_map->freeze();
5452 new_map->set_is_extensible(false);
5453 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5454 set_map(new_map);
5455 } else {
5456 // Slow path: need to normalize properties for safety
5457 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
5458 if (maybe->IsFailure()) return maybe;
5459
5460 // Create a new map, since other objects with this map may be extensible.
5461 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5462 Map* new_map;
5463 MaybeObject* maybe_copy = map()->Copy();
5464 if (!maybe_copy->To(&new_map)) return maybe_copy;
5465 new_map->freeze();
5466 new_map->set_is_extensible(false);
5467 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5468 set_map(new_map);
5469
5470 // Freeze dictionary-mode properties
5471 FreezeDictionary(property_dictionary());
5472 }
5473
5474 ASSERT(map()->has_dictionary_elements());
5475 if (new_element_dictionary != NULL) {
5476 set_elements(new_element_dictionary);
5477 }
5478
5479 if (elements() != heap->empty_slow_element_dictionary()) {
5480 SeededNumberDictionary* dictionary = element_dictionary();
5481 // Make sure we never go back to the fast case
5482 dictionary->set_requires_slow_elements();
5483 // Freeze all elements in the dictionary
5484 FreezeDictionary(dictionary);
5485 }
5486
5487 return this;
5488 }
5489
5490
5345 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { 5491 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
5346 StackLimitCheck check(isolate); 5492 StackLimitCheck check(isolate);
5347 if (check.HasOverflowed()) return isolate->StackOverflow(); 5493 if (check.HasOverflowed()) return isolate->StackOverflow();
5348 5494
5349 if (map()->is_deprecated()) { 5495 if (map()->is_deprecated()) {
5350 MaybeObject* maybe_failure = MigrateInstance(); 5496 MaybeObject* maybe_failure = MigrateInstance();
5351 if (maybe_failure->IsFailure()) return maybe_failure; 5497 if (maybe_failure->IsFailure()) return maybe_failure;
5352 } 5498 }
5353 5499
5354 Heap* heap = isolate->heap(); 5500 Heap* heap = isolate->heap();
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after
6359 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); 6505 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
6360 6506
6361 set_transitions(transitions); 6507 set_transitions(transitions);
6362 set_owns_descriptors(false); 6508 set_owns_descriptors(false);
6363 6509
6364 return result; 6510 return result;
6365 } 6511 }
6366 6512
6367 6513
6368 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, 6514 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
6515 TransitionFlag flag,
6369 Name* name, 6516 Name* name,
6370 TransitionFlag flag, 6517 SimpleTransitionFlag simple_flag) {
6371 int descriptor_index) {
6372 ASSERT(descriptors->IsSortedNoDuplicates()); 6518 ASSERT(descriptors->IsSortedNoDuplicates());
6373 6519
6374 Map* result; 6520 Map* result;
6375 MaybeObject* maybe_result = CopyDropDescriptors(); 6521 MaybeObject* maybe_result = CopyDropDescriptors();
6376 if (!maybe_result->To(&result)) return maybe_result; 6522 if (!maybe_result->To(&result)) return maybe_result;
6377 6523
6378 result->InitializeDescriptors(descriptors); 6524 result->InitializeDescriptors(descriptors);
6379 6525
6380 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 6526 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
6381 TransitionArray* transitions; 6527 TransitionArray* transitions;
6382 SimpleTransitionFlag simple_flag =
6383 (descriptor_index == descriptors->number_of_descriptors() - 1)
6384 ? SIMPLE_TRANSITION
6385 : FULL_TRANSITION;
6386 ASSERT(name == descriptors->GetKey(descriptor_index));
6387 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); 6528 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
6388 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 6529 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
6389
6390 set_transitions(transitions); 6530 set_transitions(transitions);
6391 result->SetBackPointer(this); 6531 result->SetBackPointer(this);
6392 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { 6532 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) {
6393 descriptors->InitializeRepresentations(Representation::Tagged()); 6533 descriptors->InitializeRepresentations(Representation::Tagged());
6394 } 6534 }
6395 6535
6396 return result; 6536 return result;
6397 } 6537 }
6398 6538
6399 6539
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
6495 JSFunction* ctor = JSFunction::cast(constructor()); 6635 JSFunction* ctor = JSFunction::cast(constructor());
6496 Map* map = ctor->initial_map(); 6636 Map* map = ctor->initial_map();
6497 DescriptorArray* descriptors = map->instance_descriptors(); 6637 DescriptorArray* descriptors = map->instance_descriptors();
6498 6638
6499 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 6639 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6500 DescriptorArray* new_descriptors; 6640 DescriptorArray* new_descriptors;
6501 MaybeObject* maybe_descriptors = 6641 MaybeObject* maybe_descriptors =
6502 descriptors->CopyUpTo(number_of_own_descriptors); 6642 descriptors->CopyUpTo(number_of_own_descriptors);
6503 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 6643 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
6504 6644
6505 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); 6645 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
6506 } 6646 }
6507 6647
6508 6648
6509 MaybeObject* Map::Copy() { 6649 MaybeObject* Map::Copy() {
6510 DescriptorArray* descriptors = instance_descriptors(); 6650 DescriptorArray* descriptors = instance_descriptors();
6511 DescriptorArray* new_descriptors; 6651 DescriptorArray* new_descriptors;
6512 int number_of_own_descriptors = NumberOfOwnDescriptors(); 6652 int number_of_own_descriptors = NumberOfOwnDescriptors();
6513 MaybeObject* maybe_descriptors = 6653 MaybeObject* maybe_descriptors =
6514 descriptors->CopyUpTo(number_of_own_descriptors); 6654 descriptors->CopyUpTo(number_of_own_descriptors);
6515 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 6655 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
6516 6656
6517 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); 6657 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
6518 } 6658 }
6519 6659
6520 6660
6521 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 6661 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
6522 TransitionFlag flag) { 6662 TransitionFlag flag) {
6523 DescriptorArray* descriptors = instance_descriptors(); 6663 DescriptorArray* descriptors = instance_descriptors();
6524 6664
6525 // Ensure the key is unique. 6665 // Ensure the key is unique.
6526 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); 6666 MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
6527 if (maybe_failure->IsFailure()) return maybe_failure; 6667 if (maybe_failure->IsFailure()) return maybe_failure;
(...skipping 20 matching lines...) Expand all
6548 6688
6549 if (old_size != descriptors->number_of_descriptors()) { 6689 if (old_size != descriptors->number_of_descriptors()) {
6550 new_descriptors->SetNumberOfDescriptors(new_size); 6690 new_descriptors->SetNumberOfDescriptors(new_size);
6551 new_descriptors->Set(old_size, descriptor, witness); 6691 new_descriptors->Set(old_size, descriptor, witness);
6552 new_descriptors->Sort(); 6692 new_descriptors->Sort();
6553 } else { 6693 } else {
6554 new_descriptors->Append(descriptor, witness); 6694 new_descriptors->Append(descriptor, witness);
6555 } 6695 }
6556 6696
6557 Name* key = descriptor->GetKey(); 6697 Name* key = descriptor->GetKey();
6558 int insertion_index = new_descriptors->number_of_descriptors() - 1; 6698 return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION);
6559
6560 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
6561 } 6699 }
6562 6700
6563 6701
6564 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, 6702 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
6565 TransitionFlag flag) { 6703 TransitionFlag flag) {
6566 DescriptorArray* old_descriptors = instance_descriptors(); 6704 DescriptorArray* old_descriptors = instance_descriptors();
6567 6705
6568 // Ensure the key is unique. 6706 // Ensure the key is unique.
6569 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); 6707 MaybeObject* maybe_result = descriptor->KeyToUniqueName();
6570 if (maybe_result->IsFailure()) return maybe_result; 6708 if (maybe_result->IsFailure()) return maybe_result;
6571 6709
6572 // We replace the key if it is already present. 6710 // We replace the key if it is already present.
6573 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); 6711 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
6574 if (index != DescriptorArray::kNotFound) { 6712 if (index != DescriptorArray::kNotFound) {
6575 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); 6713 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
6576 } 6714 }
6577 return CopyAddDescriptor(descriptor, flag); 6715 return CopyAddDescriptor(descriptor, flag);
6578 } 6716 }
6579 6717
6580 6718
6581 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { 6719 MaybeObject* DescriptorArray::CopyUpToAddAttributes(
6720 int enumeration_index, PropertyAttributes attributes) {
6582 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); 6721 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
6583 6722
6584 int size = enumeration_index; 6723 int size = enumeration_index;
6585 6724
6586 DescriptorArray* descriptors; 6725 DescriptorArray* descriptors;
6587 MaybeObject* maybe_descriptors = Allocate(size); 6726 MaybeObject* maybe_descriptors = Allocate(size);
6588 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; 6727 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
6589 DescriptorArray::WhitenessWitness witness(descriptors); 6728 DescriptorArray::WhitenessWitness witness(descriptors);
6590 6729
6591 for (int i = 0; i < size; ++i) { 6730 if (attributes != NONE) {
6592 descriptors->CopyFrom(i, this, i, witness); 6731 for (int i = 0; i < size; ++i) {
6732 Object* value = GetValue(i);
6733 PropertyDetails details = GetDetails(i);
6734 // READ_ONLY is an invalid attribute for JS setters/getters.
6735 if (details.type() == CALLBACKS && value->IsAccessorPair()) {
6736 attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY);
6737 }
6738 Descriptor desc(GetKey(i), value, details.CopyAddAttributes(attributes));
6739 descriptors->Set(i, &desc, witness);
6740 }
6741 } else {
6742 for (int i = 0; i < size; ++i) {
6743 descriptors->CopyFrom(i, this, i, witness);
6744 }
6593 } 6745 }
6594 6746
6595 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); 6747 if (number_of_descriptors() != enumeration_index) descriptors->Sort();
6596 6748
6597 return descriptors; 6749 return descriptors;
6598 } 6750 }
6599 6751
6600 6752
6601 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, 6753 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors,
6602 Descriptor* descriptor, 6754 Descriptor* descriptor,
(...skipping 20 matching lines...) Expand all
6623 if (i == insertion_index) { 6775 if (i == insertion_index) {
6624 new_descriptors->Set(i, descriptor, witness); 6776 new_descriptors->Set(i, descriptor, witness);
6625 } else { 6777 } else {
6626 new_descriptors->CopyFrom(i, descriptors, i, witness); 6778 new_descriptors->CopyFrom(i, descriptors, i, witness);
6627 } 6779 }
6628 } 6780 }
6629 6781
6630 // Re-sort if descriptors were removed. 6782 // Re-sort if descriptors were removed.
6631 if (new_size != descriptors->length()) new_descriptors->Sort(); 6783 if (new_size != descriptors->length()) new_descriptors->Sort();
6632 6784
6633 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); 6785 SimpleTransitionFlag simple_flag =
6786 (insertion_index == descriptors->number_of_descriptors() - 1)
6787 ? SIMPLE_TRANSITION
6788 : FULL_TRANSITION;
6789 return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag);
6634 } 6790 }
6635 6791
6636 6792
6637 void Map::UpdateCodeCache(Handle<Map> map, 6793 void Map::UpdateCodeCache(Handle<Map> map,
6638 Handle<Name> name, 6794 Handle<Name> name,
6639 Handle<Code> code) { 6795 Handle<Code> code) {
6640 Isolate* isolate = map->GetIsolate(); 6796 Isolate* isolate = map->GetIsolate();
6641 CALL_HEAP_FUNCTION_VOID(isolate, 6797 CALL_HEAP_FUNCTION_VOID(isolate,
6642 map->UpdateCodeCache(*name, *code)); 6798 map->UpdateCodeCache(*name, *code));
6643 } 6799 }
(...skipping 6732 matching lines...) Expand 10 before | Expand all | Expand 10 after
13376 13532
13377 template class HashTable<ObjectHashTableShape<2>, Object*>; 13533 template class HashTable<ObjectHashTableShape<2>, Object*>;
13378 13534
13379 template class Dictionary<NameDictionaryShape, Name*>; 13535 template class Dictionary<NameDictionaryShape, Name*>;
13380 13536
13381 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; 13537 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
13382 13538
13383 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; 13539 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
13384 13540
13385 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: 13541 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
13386 Allocate(Heap* heap, int at_least_space_for); 13542 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
13387 13543
13388 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: 13544 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
13389 Allocate(Heap* heap, int at_least_space_for); 13545 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
13390 13546
13391 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: 13547 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
13392 Allocate(Heap* heap, int n); 13548 Allocate(Heap* heap, int n, PretenureFlag pretenure);
13393 13549
13394 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( 13550 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
13395 uint32_t, Object*); 13551 uint32_t, Object*);
13396 13552
13397 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: 13553 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
13398 AtPut(uint32_t, Object*); 13554 AtPut(uint32_t, Object*);
13399 13555
13400 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: 13556 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
13401 SlowReverseLookup(Object* value); 13557 SlowReverseLookup(Object* value);
13402 13558
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after
14326 int entry = cache->FindInsertionEntry(key.Hash()); 14482 int entry = cache->FindInsertionEntry(key.Hash());
14327 cache->set(EntryToIndex(entry), array); 14483 cache->set(EntryToIndex(entry), array);
14328 cache->set(EntryToIndex(entry) + 1, value); 14484 cache->set(EntryToIndex(entry) + 1, value);
14329 cache->ElementAdded(); 14485 cache->ElementAdded();
14330 return cache; 14486 return cache;
14331 } 14487 }
14332 14488
14333 14489
14334 template<typename Shape, typename Key> 14490 template<typename Shape, typename Key>
14335 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, 14491 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap,
14336 int at_least_space_for) { 14492 int at_least_space_for,
14493 PretenureFlag pretenure) {
14337 Object* obj; 14494 Object* obj;
14338 { MaybeObject* maybe_obj = 14495 { MaybeObject* maybe_obj =
14339 HashTable<Shape, Key>::Allocate(heap, at_least_space_for); 14496 HashTable<Shape, Key>::Allocate(
14497 heap,
14498 at_least_space_for,
14499 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY,
14500 pretenure);
14340 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 14501 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
14341 } 14502 }
14342 // Initialize the next enumeration index. 14503 // Initialize the next enumeration index.
14343 Dictionary<Shape, Key>::cast(obj)-> 14504 Dictionary<Shape, Key>::cast(obj)->
14344 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); 14505 SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
14345 return obj; 14506 return obj;
14346 } 14507 }
14347 14508
14348 14509
14349 void NameDictionary::DoGenerateNewEnumerationIndices( 14510 void NameDictionary::DoGenerateNewEnumerationIndices(
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after
15454 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 15615 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
15455 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 15616 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
15456 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 15617 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
15457 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 15618 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
15458 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 15619 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
15459 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 15620 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
15460 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 15621 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
15461 } 15622 }
15462 15623
15463 } } // namespace v8::internal 15624 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698