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 |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |