OLD | NEW |
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 Loading... |
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 | |
4546 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4510 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
4547 Handle<JSObject> object) { | 4511 Handle<JSObject> object) { |
4548 CALL_HEAP_FUNCTION(object->GetIsolate(), | 4512 CALL_HEAP_FUNCTION(object->GetIsolate(), |
4549 object->NormalizeElements(), | 4513 object->NormalizeElements(), |
4550 SeededNumberDictionary); | 4514 SeededNumberDictionary); |
4551 } | 4515 } |
4552 | 4516 |
4553 | 4517 |
4554 MaybeObject* JSObject::NormalizeElements() { | 4518 MaybeObject* JSObject::NormalizeElements() { |
4555 ASSERT(!HasExternalArrayElements()); | 4519 ASSERT(!HasExternalArrayElements()); |
(...skipping 11 matching lines...) Expand all Loading... |
4567 ASSERT(HasFastSmiOrObjectElements() || | 4531 ASSERT(HasFastSmiOrObjectElements() || |
4568 HasFastDoubleElements() || | 4532 HasFastDoubleElements() || |
4569 HasFastArgumentsElements()); | 4533 HasFastArgumentsElements()); |
4570 // Compute the effective length and allocate a new backing store. | 4534 // Compute the effective length and allocate a new backing store. |
4571 int length = IsJSArray() | 4535 int length = IsJSArray() |
4572 ? Smi::cast(JSArray::cast(this)->length())->value() | 4536 ? Smi::cast(JSArray::cast(this)->length())->value() |
4573 : array->length(); | 4537 : array->length(); |
4574 int old_capacity = 0; | 4538 int old_capacity = 0; |
4575 int used_elements = 0; | 4539 int used_elements = 0; |
4576 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 4540 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
4577 SeededNumberDictionary* dictionary; | 4541 SeededNumberDictionary* dictionary = NULL; |
4578 MaybeObject* maybe_dictionary = | 4542 { Object* object; |
4579 SeededNumberDictionary::Allocate(GetHeap(), used_elements); | 4543 MaybeObject* maybe = |
4580 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 4544 SeededNumberDictionary::Allocate(GetHeap(), used_elements); |
| 4545 if (!maybe->ToObject(&object)) return maybe; |
| 4546 dictionary = SeededNumberDictionary::cast(object); |
| 4547 } |
4581 | 4548 |
4582 maybe_dictionary = CopyFastElementsToDictionary( | 4549 // Copy the elements to the new backing store. |
4583 GetIsolate(), array, length, dictionary); | 4550 bool has_double_elements = array->IsFixedDoubleArray(); |
4584 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 4551 for (int i = 0; i < length; i++) { |
| 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 } |
4585 | 4579 |
4586 // Switch to using the dictionary as the backing storage for elements. | 4580 // Switch to using the dictionary as the backing storage for elements. |
4587 if (is_arguments) { | 4581 if (is_arguments) { |
4588 FixedArray::cast(elements())->set(1, dictionary); | 4582 FixedArray::cast(elements())->set(1, dictionary); |
4589 } else { | 4583 } else { |
4590 // Set the new map first to satify the elements type assert in | 4584 // Set the new map first to satify the elements type assert in |
4591 // set_elements(). | 4585 // set_elements(). |
4592 Map* new_map; | 4586 Object* new_map; |
4593 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), | 4587 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), |
4594 DICTIONARY_ELEMENTS); | 4588 DICTIONARY_ELEMENTS); |
4595 if (!maybe->To(&new_map)) return maybe; | 4589 if (!maybe->ToObject(&new_map)) return maybe; |
4596 set_map(new_map); | 4590 set_map(Map::cast(new_map)); |
4597 set_elements(dictionary); | 4591 set_elements(dictionary); |
4598 } | 4592 } |
4599 | 4593 |
4600 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> | 4594 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> |
4601 Increment(); | 4595 Increment(); |
4602 | 4596 |
4603 #ifdef DEBUG | 4597 #ifdef DEBUG |
4604 if (FLAG_trace_normalization) { | 4598 if (FLAG_trace_normalization) { |
4605 PrintF("Object elements have been normalized:\n"); | 4599 PrintF("Object elements have been normalized:\n"); |
4606 Print(); | 4600 Print(); |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5330 SeededNumberDictionary* dictionary = NULL; | 5324 SeededNumberDictionary* dictionary = NULL; |
5331 { MaybeObject* maybe = NormalizeElements(); | 5325 { MaybeObject* maybe = NormalizeElements(); |
5332 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; | 5326 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; |
5333 } | 5327 } |
5334 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 5328 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
5335 // Make sure that we never go back to fast case. | 5329 // Make sure that we never go back to fast case. |
5336 dictionary->set_requires_slow_elements(); | 5330 dictionary->set_requires_slow_elements(); |
5337 | 5331 |
5338 // Do a map transition, other objects with this map may still | 5332 // Do a map transition, other objects with this map may still |
5339 // be extensible. | 5333 // be extensible. |
5340 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | |
5341 Map* new_map; | 5334 Map* new_map; |
5342 MaybeObject* maybe = map()->Copy(); | 5335 MaybeObject* maybe = map()->Copy(); |
5343 if (!maybe->To(&new_map)) return maybe; | 5336 if (!maybe->To(&new_map)) return maybe; |
5344 | 5337 |
5345 new_map->set_is_extensible(false); | 5338 new_map->set_is_extensible(false); |
5346 set_map(new_map); | 5339 set_map(new_map); |
5347 ASSERT(!map()->is_extensible()); | 5340 ASSERT(!map()->is_extensible()); |
5348 return new_map; | 5341 return new_map; |
5349 } | 5342 } |
5350 | 5343 |
5351 | 5344 |
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 details = details.CopyAddAttributes(FROZEN); | |
5360 dictionary->DetailsAtPut(i, details); | |
5361 } | |
5362 } | |
5363 } | |
5364 | |
5365 | |
5366 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) { | |
5367 // Freezing non-strict arguments should be handled elsewhere. | |
5368 ASSERT(!HasNonStrictArgumentsElements()); | |
5369 | |
5370 Heap* heap = isolate->heap(); | |
5371 | |
5372 if (map()->is_frozen()) return this; | |
5373 | |
5374 if (IsAccessCheckNeeded() && | |
5375 !isolate->MayNamedAccess(this, | |
5376 heap->undefined_value(), | |
5377 v8::ACCESS_KEYS)) { | |
5378 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); | |
5379 return heap->false_value(); | |
5380 } | |
5381 | |
5382 if (IsJSGlobalProxy()) { | |
5383 Object* proto = GetPrototype(); | |
5384 if (proto->IsNull()) return this; | |
5385 ASSERT(proto->IsJSGlobalObject()); | |
5386 return JSObject::cast(proto)->Freeze(isolate); | |
5387 } | |
5388 | |
5389 // It's not possible to freeze objects with external array elements | |
5390 if (HasExternalArrayElements()) { | |
5391 HandleScope scope(isolate); | |
5392 Handle<Object> object(this, isolate); | |
5393 Handle<Object> error = | |
5394 isolate->factory()->NewTypeError( | |
5395 "cant_prevent_ext_external_array_elements", | |
5396 HandleVector(&object, 1)); | |
5397 return isolate->Throw(*error); | |
5398 } | |
5399 | |
5400 SeededNumberDictionary* new_element_dictionary = NULL; | |
5401 if (!elements()->IsDictionary()) { | |
5402 int length = IsJSArray() | |
5403 ? Smi::cast(JSArray::cast(this)->length())->value() | |
5404 : elements()->length(); | |
5405 if (length > 0) { | |
5406 int capacity = 0; | |
5407 int used = 0; | |
5408 GetElementsCapacityAndUsage(&capacity, &used); | |
5409 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used); | |
5410 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | |
5411 | |
5412 // Move elements to a dictionary; avoid calling NormalizeElements to avoid | |
5413 // unnecessary transitions. | |
5414 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length, | |
5415 new_element_dictionary); | |
5416 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | |
5417 } else { | |
5418 // No existing elements, use a pre-allocated empty backing store | |
5419 new_element_dictionary = heap->empty_slow_element_dictionary(); | |
5420 } | |
5421 } | |
5422 | |
5423 LookupResult result(isolate); | |
5424 map()->LookupTransition(this, heap->frozen_symbol(), &result); | |
5425 if (result.IsTransition()) { | |
5426 Map* transition_map = result.GetTransitionTarget(); | |
5427 ASSERT(transition_map->has_dictionary_elements()); | |
5428 ASSERT(transition_map->is_frozen()); | |
5429 ASSERT(!transition_map->is_extensible()); | |
5430 set_map(transition_map); | |
5431 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) { | |
5432 // Create a new descriptor array with fully-frozen properties | |
5433 int num_descriptors = map()->NumberOfOwnDescriptors(); | |
5434 DescriptorArray* new_descriptors; | |
5435 MaybeObject* maybe_descriptors = | |
5436 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors, | |
5437 FROZEN); | |
5438 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
5439 | |
5440 Map* new_map; | |
5441 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors( | |
5442 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol()); | |
5443 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
5444 new_map->freeze(); | |
5445 new_map->set_is_extensible(false); | |
5446 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | |
5447 set_map(new_map); | |
5448 } else { | |
5449 // Slow path: need to normalize properties for safety | |
5450 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | |
5451 if (maybe->IsFailure()) return maybe; | |
5452 | |
5453 // Create a new map, since other objects with this map may be extensible. | |
5454 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | |
5455 Map* new_map; | |
5456 MaybeObject* maybe_copy = map()->Copy(); | |
5457 if (!maybe_copy->To(&new_map)) return maybe_copy; | |
5458 new_map->freeze(); | |
5459 new_map->set_is_extensible(false); | |
5460 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | |
5461 set_map(new_map); | |
5462 | |
5463 // Freeze dictionary-mode properties | |
5464 FreezeDictionary(property_dictionary()); | |
5465 } | |
5466 | |
5467 ASSERT(map()->has_dictionary_elements()); | |
5468 if (new_element_dictionary != NULL) { | |
5469 set_elements(new_element_dictionary); | |
5470 } | |
5471 | |
5472 if (elements() != heap->empty_slow_element_dictionary()) { | |
5473 SeededNumberDictionary* dictionary = element_dictionary(); | |
5474 // Make sure we never go back to the fast case | |
5475 dictionary->set_requires_slow_elements(); | |
5476 // Freeze all elements in the dictionary | |
5477 FreezeDictionary(dictionary); | |
5478 } | |
5479 | |
5480 return this; | |
5481 } | |
5482 | |
5483 | |
5484 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { | 5345 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { |
5485 StackLimitCheck check(isolate); | 5346 StackLimitCheck check(isolate); |
5486 if (check.HasOverflowed()) return isolate->StackOverflow(); | 5347 if (check.HasOverflowed()) return isolate->StackOverflow(); |
5487 | 5348 |
5488 if (map()->is_deprecated()) { | 5349 if (map()->is_deprecated()) { |
5489 MaybeObject* maybe_failure = MigrateInstance(); | 5350 MaybeObject* maybe_failure = MigrateInstance(); |
5490 if (maybe_failure->IsFailure()) return maybe_failure; | 5351 if (maybe_failure->IsFailure()) return maybe_failure; |
5491 } | 5352 } |
5492 | 5353 |
5493 Heap* heap = isolate->heap(); | 5354 Heap* heap = isolate->heap(); |
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6498 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 6359 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
6499 | 6360 |
6500 set_transitions(transitions); | 6361 set_transitions(transitions); |
6501 set_owns_descriptors(false); | 6362 set_owns_descriptors(false); |
6502 | 6363 |
6503 return result; | 6364 return result; |
6504 } | 6365 } |
6505 | 6366 |
6506 | 6367 |
6507 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 6368 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
| 6369 Name* name, |
6508 TransitionFlag flag, | 6370 TransitionFlag flag, |
6509 Name* name, | 6371 int descriptor_index) { |
6510 SimpleTransitionFlag simple_flag) { | |
6511 ASSERT(descriptors->IsSortedNoDuplicates()); | 6372 ASSERT(descriptors->IsSortedNoDuplicates()); |
6512 | 6373 |
6513 Map* result; | 6374 Map* result; |
6514 MaybeObject* maybe_result = CopyDropDescriptors(); | 6375 MaybeObject* maybe_result = CopyDropDescriptors(); |
6515 if (!maybe_result->To(&result)) return maybe_result; | 6376 if (!maybe_result->To(&result)) return maybe_result; |
6516 | 6377 |
6517 result->InitializeDescriptors(descriptors); | 6378 result->InitializeDescriptors(descriptors); |
6518 | 6379 |
6519 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6380 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
6520 TransitionArray* transitions; | 6381 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)); |
6521 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6387 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
6522 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6388 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 6389 |
6523 set_transitions(transitions); | 6390 set_transitions(transitions); |
6524 result->SetBackPointer(this); | 6391 result->SetBackPointer(this); |
6525 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { | 6392 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { |
6526 descriptors->InitializeRepresentations(Representation::Tagged()); | 6393 descriptors->InitializeRepresentations(Representation::Tagged()); |
6527 } | 6394 } |
6528 | 6395 |
6529 return result; | 6396 return result; |
6530 } | 6397 } |
6531 | 6398 |
6532 | 6399 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6628 JSFunction* ctor = JSFunction::cast(constructor()); | 6495 JSFunction* ctor = JSFunction::cast(constructor()); |
6629 Map* map = ctor->initial_map(); | 6496 Map* map = ctor->initial_map(); |
6630 DescriptorArray* descriptors = map->instance_descriptors(); | 6497 DescriptorArray* descriptors = map->instance_descriptors(); |
6631 | 6498 |
6632 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6499 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
6633 DescriptorArray* new_descriptors; | 6500 DescriptorArray* new_descriptors; |
6634 MaybeObject* maybe_descriptors = | 6501 MaybeObject* maybe_descriptors = |
6635 descriptors->CopyUpTo(number_of_own_descriptors); | 6502 descriptors->CopyUpTo(number_of_own_descriptors); |
6636 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6503 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
6637 | 6504 |
6638 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6505 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); |
6639 } | 6506 } |
6640 | 6507 |
6641 | 6508 |
6642 MaybeObject* Map::Copy() { | 6509 MaybeObject* Map::Copy() { |
6643 DescriptorArray* descriptors = instance_descriptors(); | 6510 DescriptorArray* descriptors = instance_descriptors(); |
6644 DescriptorArray* new_descriptors; | 6511 DescriptorArray* new_descriptors; |
6645 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6512 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
6646 MaybeObject* maybe_descriptors = | 6513 MaybeObject* maybe_descriptors = |
6647 descriptors->CopyUpTo(number_of_own_descriptors); | 6514 descriptors->CopyUpTo(number_of_own_descriptors); |
6648 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6515 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
6649 | 6516 |
6650 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6517 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); |
6651 } | 6518 } |
6652 | 6519 |
6653 | 6520 |
6654 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, | 6521 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
6655 TransitionFlag flag) { | 6522 TransitionFlag flag) { |
6656 DescriptorArray* descriptors = instance_descriptors(); | 6523 DescriptorArray* descriptors = instance_descriptors(); |
6657 | 6524 |
6658 // Ensure the key is unique. | 6525 // Ensure the key is unique. |
6659 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); | 6526 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); |
6660 if (maybe_failure->IsFailure()) return maybe_failure; | 6527 if (maybe_failure->IsFailure()) return maybe_failure; |
(...skipping 20 matching lines...) Expand all Loading... |
6681 | 6548 |
6682 if (old_size != descriptors->number_of_descriptors()) { | 6549 if (old_size != descriptors->number_of_descriptors()) { |
6683 new_descriptors->SetNumberOfDescriptors(new_size); | 6550 new_descriptors->SetNumberOfDescriptors(new_size); |
6684 new_descriptors->Set(old_size, descriptor, witness); | 6551 new_descriptors->Set(old_size, descriptor, witness); |
6685 new_descriptors->Sort(); | 6552 new_descriptors->Sort(); |
6686 } else { | 6553 } else { |
6687 new_descriptors->Append(descriptor, witness); | 6554 new_descriptors->Append(descriptor, witness); |
6688 } | 6555 } |
6689 | 6556 |
6690 Name* key = descriptor->GetKey(); | 6557 Name* key = descriptor->GetKey(); |
6691 return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION); | 6558 int insertion_index = new_descriptors->number_of_descriptors() - 1; |
| 6559 |
| 6560 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); |
6692 } | 6561 } |
6693 | 6562 |
6694 | 6563 |
6695 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, | 6564 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
6696 TransitionFlag flag) { | 6565 TransitionFlag flag) { |
6697 DescriptorArray* old_descriptors = instance_descriptors(); | 6566 DescriptorArray* old_descriptors = instance_descriptors(); |
6698 | 6567 |
6699 // Ensure the key is unique. | 6568 // Ensure the key is unique. |
6700 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); | 6569 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); |
6701 if (maybe_result->IsFailure()) return maybe_result; | 6570 if (maybe_result->IsFailure()) return maybe_result; |
6702 | 6571 |
6703 // We replace the key if it is already present. | 6572 // We replace the key if it is already present. |
6704 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 6573 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
6705 if (index != DescriptorArray::kNotFound) { | 6574 if (index != DescriptorArray::kNotFound) { |
6706 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); | 6575 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); |
6707 } | 6576 } |
6708 return CopyAddDescriptor(descriptor, flag); | 6577 return CopyAddDescriptor(descriptor, flag); |
6709 } | 6578 } |
6710 | 6579 |
6711 | 6580 |
6712 MaybeObject* DescriptorArray::CopyUpToAddAttributes( | 6581 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { |
6713 int enumeration_index, PropertyAttributes attributes) { | |
6714 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | 6582 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
6715 | 6583 |
6716 int size = enumeration_index; | 6584 int size = enumeration_index; |
6717 | 6585 |
6718 DescriptorArray* descriptors; | 6586 DescriptorArray* descriptors; |
6719 MaybeObject* maybe_descriptors = Allocate(size); | 6587 MaybeObject* maybe_descriptors = Allocate(size); |
6720 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 6588 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
6721 DescriptorArray::WhitenessWitness witness(descriptors); | 6589 DescriptorArray::WhitenessWitness witness(descriptors); |
6722 | 6590 |
6723 if (attributes != NONE) { | 6591 for (int i = 0; i < size; ++i) { |
6724 for (int i = 0; i < size; ++i) { | 6592 descriptors->CopyFrom(i, this, i, witness); |
6725 PropertyDetails details = GetDetails(i).CopyAddAttributes(attributes); | |
6726 Descriptor desc(GetKey(i), GetValue(i), details); | |
6727 descriptors->Set(i, &desc, witness); | |
6728 } | |
6729 } else { | |
6730 for (int i = 0; i < size; ++i) { | |
6731 descriptors->CopyFrom(i, this, i, witness); | |
6732 } | |
6733 } | 6593 } |
6734 | 6594 |
6735 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); | 6595 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); |
6736 | 6596 |
6737 return descriptors; | 6597 return descriptors; |
6738 } | 6598 } |
6739 | 6599 |
6740 | 6600 |
6741 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, | 6601 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, |
6742 Descriptor* descriptor, | 6602 Descriptor* descriptor, |
(...skipping 20 matching lines...) Expand all Loading... |
6763 if (i == insertion_index) { | 6623 if (i == insertion_index) { |
6764 new_descriptors->Set(i, descriptor, witness); | 6624 new_descriptors->Set(i, descriptor, witness); |
6765 } else { | 6625 } else { |
6766 new_descriptors->CopyFrom(i, descriptors, i, witness); | 6626 new_descriptors->CopyFrom(i, descriptors, i, witness); |
6767 } | 6627 } |
6768 } | 6628 } |
6769 | 6629 |
6770 // Re-sort if descriptors were removed. | 6630 // Re-sort if descriptors were removed. |
6771 if (new_size != descriptors->length()) new_descriptors->Sort(); | 6631 if (new_size != descriptors->length()) new_descriptors->Sort(); |
6772 | 6632 |
6773 SimpleTransitionFlag simple_flag = | 6633 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); |
6774 (insertion_index == descriptors->number_of_descriptors() - 1) | |
6775 ? SIMPLE_TRANSITION | |
6776 : FULL_TRANSITION; | |
6777 return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag); | |
6778 } | 6634 } |
6779 | 6635 |
6780 | 6636 |
6781 void Map::UpdateCodeCache(Handle<Map> map, | 6637 void Map::UpdateCodeCache(Handle<Map> map, |
6782 Handle<Name> name, | 6638 Handle<Name> name, |
6783 Handle<Code> code) { | 6639 Handle<Code> code) { |
6784 Isolate* isolate = map->GetIsolate(); | 6640 Isolate* isolate = map->GetIsolate(); |
6785 CALL_HEAP_FUNCTION_VOID(isolate, | 6641 CALL_HEAP_FUNCTION_VOID(isolate, |
6786 map->UpdateCodeCache(*name, *code)); | 6642 map->UpdateCodeCache(*name, *code)); |
6787 } | 6643 } |
(...skipping 6732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13520 | 13376 |
13521 template class HashTable<ObjectHashTableShape<2>, Object*>; | 13377 template class HashTable<ObjectHashTableShape<2>, Object*>; |
13522 | 13378 |
13523 template class Dictionary<NameDictionaryShape, Name*>; | 13379 template class Dictionary<NameDictionaryShape, Name*>; |
13524 | 13380 |
13525 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; | 13381 template class Dictionary<SeededNumberDictionaryShape, uint32_t>; |
13526 | 13382 |
13527 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; | 13383 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; |
13528 | 13384 |
13529 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: | 13385 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
13530 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure); | 13386 Allocate(Heap* heap, int at_least_space_for); |
13531 | 13387 |
13532 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: | 13388 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
13533 Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure); | 13389 Allocate(Heap* heap, int at_least_space_for); |
13534 | 13390 |
13535 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: | 13391 template MaybeObject* Dictionary<NameDictionaryShape, Name*>:: |
13536 Allocate(Heap* heap, int n, PretenureFlag pretenure); | 13392 Allocate(Heap* heap, int n); |
13537 | 13393 |
13538 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( | 13394 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( |
13539 uint32_t, Object*); | 13395 uint32_t, Object*); |
13540 | 13396 |
13541 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: | 13397 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
13542 AtPut(uint32_t, Object*); | 13398 AtPut(uint32_t, Object*); |
13543 | 13399 |
13544 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: | 13400 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
13545 SlowReverseLookup(Object* value); | 13401 SlowReverseLookup(Object* value); |
13546 | 13402 |
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14470 int entry = cache->FindInsertionEntry(key.Hash()); | 14326 int entry = cache->FindInsertionEntry(key.Hash()); |
14471 cache->set(EntryToIndex(entry), array); | 14327 cache->set(EntryToIndex(entry), array); |
14472 cache->set(EntryToIndex(entry) + 1, value); | 14328 cache->set(EntryToIndex(entry) + 1, value); |
14473 cache->ElementAdded(); | 14329 cache->ElementAdded(); |
14474 return cache; | 14330 return cache; |
14475 } | 14331 } |
14476 | 14332 |
14477 | 14333 |
14478 template<typename Shape, typename Key> | 14334 template<typename Shape, typename Key> |
14479 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, | 14335 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, |
14480 int at_least_space_for, | 14336 int at_least_space_for) { |
14481 PretenureFlag pretenure) { | |
14482 Object* obj; | 14337 Object* obj; |
14483 { MaybeObject* maybe_obj = | 14338 { MaybeObject* maybe_obj = |
14484 HashTable<Shape, Key>::Allocate( | 14339 HashTable<Shape, Key>::Allocate(heap, at_least_space_for); |
14485 heap, | |
14486 at_least_space_for, | |
14487 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY, | |
14488 pretenure); | |
14489 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 14340 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
14490 } | 14341 } |
14491 // Initialize the next enumeration index. | 14342 // Initialize the next enumeration index. |
14492 Dictionary<Shape, Key>::cast(obj)-> | 14343 Dictionary<Shape, Key>::cast(obj)-> |
14493 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 14344 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
14494 return obj; | 14345 return obj; |
14495 } | 14346 } |
14496 | 14347 |
14497 | 14348 |
14498 void NameDictionary::DoGenerateNewEnumerationIndices( | 14349 void NameDictionary::DoGenerateNewEnumerationIndices( |
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15603 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 15454 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
15604 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15455 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
15605 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15456 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
15606 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15457 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
15607 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15458 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
15608 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15459 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
15609 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15460 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
15610 } | 15461 } |
15611 | 15462 |
15612 } } // namespace v8::internal | 15463 } } // namespace v8::internal |
OLD | NEW |