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 4607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4618 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); | 4618 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); |
4619 MaybeObject* maybe_result = | 4619 MaybeObject* maybe_result = |
4620 dictionary->AddNumberEntry(i, value, details); | 4620 dictionary->AddNumberEntry(i, value, details); |
4621 if (!maybe_result->To(&dictionary)) return maybe_result; | 4621 if (!maybe_result->To(&dictionary)) return maybe_result; |
4622 } | 4622 } |
4623 } | 4623 } |
4624 return dictionary; | 4624 return dictionary; |
4625 } | 4625 } |
4626 | 4626 |
4627 | 4627 |
| 4628 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( |
| 4629 Handle<FixedArrayBase> array, |
| 4630 int length, |
| 4631 Handle<SeededNumberDictionary> dict) { |
| 4632 Isolate* isolate = array->GetIsolate(); |
| 4633 CALL_HEAP_FUNCTION(isolate, |
| 4634 CopyFastElementsToDictionary( |
| 4635 isolate, *array, length, *dict), |
| 4636 SeededNumberDictionary); |
| 4637 } |
| 4638 |
| 4639 |
4628 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4640 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
4629 Handle<JSObject> object) { | 4641 Handle<JSObject> object) { |
4630 CALL_HEAP_FUNCTION(object->GetIsolate(), | 4642 CALL_HEAP_FUNCTION(object->GetIsolate(), |
4631 object->NormalizeElements(), | 4643 object->NormalizeElements(), |
4632 SeededNumberDictionary); | 4644 SeededNumberDictionary); |
4633 } | 4645 } |
4634 | 4646 |
4635 | 4647 |
4636 MaybeObject* JSObject::NormalizeElements() { | 4648 MaybeObject* JSObject::NormalizeElements() { |
4637 ASSERT(!HasExternalArrayElements()); | 4649 ASSERT(!HasExternalArrayElements()); |
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5433 attrs |= READ_ONLY; | 5445 attrs |= READ_ONLY; |
5434 } | 5446 } |
5435 details = details.CopyAddAttributes( | 5447 details = details.CopyAddAttributes( |
5436 static_cast<PropertyAttributes>(attrs)); | 5448 static_cast<PropertyAttributes>(attrs)); |
5437 dictionary->DetailsAtPut(i, details); | 5449 dictionary->DetailsAtPut(i, details); |
5438 } | 5450 } |
5439 } | 5451 } |
5440 } | 5452 } |
5441 | 5453 |
5442 | 5454 |
5443 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) { | 5455 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { |
5444 // Freezing non-strict arguments should be handled elsewhere. | 5456 // Freezing non-strict arguments should be handled elsewhere. |
5445 ASSERT(!HasNonStrictArgumentsElements()); | 5457 ASSERT(!object->HasNonStrictArgumentsElements()); |
5446 | 5458 |
5447 Heap* heap = isolate->heap(); | 5459 if (object->map()->is_frozen()) return object; |
5448 | 5460 |
5449 if (map()->is_frozen()) return this; | 5461 Isolate* isolate = object->GetIsolate(); |
5450 | 5462 if (object->IsAccessCheckNeeded() && |
5451 if (IsAccessCheckNeeded() && | 5463 !isolate->MayNamedAccess(*object, |
5452 !isolate->MayNamedAccess(this, | 5464 isolate->heap()->undefined_value(), |
5453 heap->undefined_value(), | |
5454 v8::ACCESS_KEYS)) { | 5465 v8::ACCESS_KEYS)) { |
5455 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); | 5466 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); |
5456 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5467 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5457 return heap->false_value(); | 5468 return isolate->factory()->false_value(); |
5458 } | 5469 } |
5459 | 5470 |
5460 if (IsJSGlobalProxy()) { | 5471 if (object->IsJSGlobalProxy()) { |
5461 Object* proto = GetPrototype(); | 5472 Handle<Object> proto(object->GetPrototype(), isolate); |
5462 if (proto->IsNull()) return this; | 5473 if (proto->IsNull()) return object; |
5463 ASSERT(proto->IsJSGlobalObject()); | 5474 ASSERT(proto->IsJSGlobalObject()); |
5464 return JSObject::cast(proto)->Freeze(isolate); | 5475 return Freeze(Handle<JSObject>::cast(proto)); |
5465 } | 5476 } |
5466 | 5477 |
5467 // It's not possible to freeze objects with external array elements | 5478 // It's not possible to freeze objects with external array elements |
5468 if (HasExternalArrayElements()) { | 5479 if (object->HasExternalArrayElements()) { |
5469 HandleScope scope(isolate); | |
5470 Handle<Object> object(this, isolate); | |
5471 Handle<Object> error = | 5480 Handle<Object> error = |
5472 isolate->factory()->NewTypeError( | 5481 isolate->factory()->NewTypeError( |
5473 "cant_prevent_ext_external_array_elements", | 5482 "cant_prevent_ext_external_array_elements", |
5474 HandleVector(&object, 1)); | 5483 HandleVector(&object, 1)); |
5475 return isolate->Throw(*error); | 5484 isolate->Throw(*error); |
| 5485 return Handle<Object>(); |
5476 } | 5486 } |
5477 | 5487 |
5478 SeededNumberDictionary* new_element_dictionary = NULL; | 5488 Handle<SeededNumberDictionary> new_element_dictionary; |
5479 if (!elements()->IsDictionary()) { | 5489 if (!object->elements()->IsDictionary()) { |
5480 int length = IsJSArray() | 5490 int length = object->IsJSArray() |
5481 ? Smi::cast(JSArray::cast(this)->length())->value() | 5491 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
5482 : elements()->length(); | 5492 : object->elements()->length(); |
5483 if (length > 0) { | 5493 if (length > 0) { |
5484 int capacity = 0; | 5494 int capacity = 0; |
5485 int used = 0; | 5495 int used = 0; |
5486 GetElementsCapacityAndUsage(&capacity, &used); | 5496 object->GetElementsCapacityAndUsage(&capacity, &used); |
5487 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used); | 5497 new_element_dictionary = |
5488 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | 5498 isolate->factory()->NewSeededNumberDictionary(used); |
5489 | 5499 |
5490 // Move elements to a dictionary; avoid calling NormalizeElements to avoid | 5500 // Move elements to a dictionary; avoid calling NormalizeElements to avoid |
5491 // unnecessary transitions. | 5501 // unnecessary transitions. |
5492 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length, | 5502 new_element_dictionary = CopyFastElementsToDictionary( |
5493 new_element_dictionary); | 5503 handle(object->elements()), length, new_element_dictionary); |
5494 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | |
5495 } else { | 5504 } else { |
5496 // No existing elements, use a pre-allocated empty backing store | 5505 // No existing elements, use a pre-allocated empty backing store |
5497 new_element_dictionary = heap->empty_slow_element_dictionary(); | 5506 new_element_dictionary = |
| 5507 isolate->factory()->empty_slow_element_dictionary(); |
5498 } | 5508 } |
5499 } | 5509 } |
5500 | 5510 |
5501 LookupResult result(isolate); | 5511 LookupResult result(isolate); |
5502 map()->LookupTransition(this, heap->frozen_symbol(), &result); | 5512 Handle<Map> old_map(object->map()); |
| 5513 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result); |
5503 if (result.IsTransition()) { | 5514 if (result.IsTransition()) { |
5504 Map* transition_map = result.GetTransitionTarget(); | 5515 Map* transition_map = result.GetTransitionTarget(); |
5505 ASSERT(transition_map->has_dictionary_elements()); | 5516 ASSERT(transition_map->has_dictionary_elements()); |
5506 ASSERT(transition_map->is_frozen()); | 5517 ASSERT(transition_map->is_frozen()); |
5507 ASSERT(!transition_map->is_extensible()); | 5518 ASSERT(!transition_map->is_extensible()); |
5508 set_map(transition_map); | 5519 object->set_map(transition_map); |
5509 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) { | 5520 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
5510 // Create a new descriptor array with fully-frozen properties | 5521 // Create a new descriptor array with fully-frozen properties |
5511 int num_descriptors = map()->NumberOfOwnDescriptors(); | 5522 int num_descriptors = old_map->NumberOfOwnDescriptors(); |
5512 DescriptorArray* new_descriptors; | 5523 Handle<DescriptorArray> new_descriptors = |
5513 MaybeObject* maybe_descriptors = | 5524 DescriptorArray::CopyUpToAddAttributes( |
5514 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors, | 5525 handle(old_map->instance_descriptors()), num_descriptors, FROZEN); |
5515 FROZEN); | 5526 Handle<Map> new_map = Map::CopyReplaceDescriptors( |
5516 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5527 old_map, new_descriptors, INSERT_TRANSITION, |
5517 | 5528 isolate->factory()->frozen_symbol()); |
5518 Map* new_map; | |
5519 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors( | |
5520 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol()); | |
5521 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
5522 new_map->freeze(); | 5529 new_map->freeze(); |
5523 new_map->set_is_extensible(false); | 5530 new_map->set_is_extensible(false); |
5524 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5531 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
5525 set_map(new_map); | 5532 object->set_map(*new_map); |
5526 } else { | 5533 } else { |
5527 // Slow path: need to normalize properties for safety | 5534 // Slow path: need to normalize properties for safety |
5528 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 5535 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
5529 if (maybe->IsFailure()) return maybe; | |
5530 | 5536 |
5531 // Create a new map, since other objects with this map may be extensible. | 5537 // Create a new map, since other objects with this map may be extensible. |
5532 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5538 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
5533 Map* new_map; | 5539 Handle<Map> new_map = Map::Copy(handle(object->map())); |
5534 MaybeObject* maybe_copy = map()->Copy(); | |
5535 if (!maybe_copy->To(&new_map)) return maybe_copy; | |
5536 new_map->freeze(); | 5540 new_map->freeze(); |
5537 new_map->set_is_extensible(false); | 5541 new_map->set_is_extensible(false); |
5538 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5542 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
5539 set_map(new_map); | 5543 object->set_map(*new_map); |
5540 | 5544 |
5541 // Freeze dictionary-mode properties | 5545 // Freeze dictionary-mode properties |
5542 FreezeDictionary(property_dictionary()); | 5546 FreezeDictionary(object->property_dictionary()); |
5543 } | 5547 } |
5544 | 5548 |
5545 ASSERT(map()->has_dictionary_elements()); | 5549 ASSERT(object->map()->has_dictionary_elements()); |
5546 if (new_element_dictionary != NULL) { | 5550 if (!new_element_dictionary.is_null()) { |
5547 set_elements(new_element_dictionary); | 5551 object->set_elements(*new_element_dictionary); |
5548 } | 5552 } |
5549 | 5553 |
5550 if (elements() != heap->empty_slow_element_dictionary()) { | 5554 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
5551 SeededNumberDictionary* dictionary = element_dictionary(); | 5555 SeededNumberDictionary* dictionary = object->element_dictionary(); |
5552 // Make sure we never go back to the fast case | 5556 // Make sure we never go back to the fast case |
5553 dictionary->set_requires_slow_elements(); | 5557 dictionary->set_requires_slow_elements(); |
5554 // Freeze all elements in the dictionary | 5558 // Freeze all elements in the dictionary |
5555 FreezeDictionary(dictionary); | 5559 FreezeDictionary(dictionary); |
5556 } | 5560 } |
5557 | 5561 |
5558 return this; | 5562 return object; |
5559 } | 5563 } |
5560 | 5564 |
5561 | 5565 |
5562 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { | 5566 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { |
5563 if (map()->is_observed()) | 5567 if (map()->is_observed()) |
5564 return isolate->heap()->undefined_value(); | 5568 return isolate->heap()->undefined_value(); |
5565 | 5569 |
5566 Heap* heap = isolate->heap(); | 5570 Heap* heap = isolate->heap(); |
5567 | 5571 |
5568 if (!HasExternalArrayElements()) { | 5572 if (!HasExternalArrayElements()) { |
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6606 result->InitializeDescriptors(new_descriptors); | 6610 result->InitializeDescriptors(new_descriptors); |
6607 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 6611 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
6608 | 6612 |
6609 set_transitions(transitions); | 6613 set_transitions(transitions); |
6610 set_owns_descriptors(false); | 6614 set_owns_descriptors(false); |
6611 | 6615 |
6612 return result; | 6616 return result; |
6613 } | 6617 } |
6614 | 6618 |
6615 | 6619 |
| 6620 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
| 6621 Handle<DescriptorArray> descriptors, |
| 6622 TransitionFlag flag, |
| 6623 Handle<Name> name) { |
| 6624 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6625 map->CopyReplaceDescriptors(*descriptors, flag, *name), |
| 6626 Map); |
| 6627 } |
| 6628 |
| 6629 |
6616 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 6630 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
6617 TransitionFlag flag, | 6631 TransitionFlag flag, |
6618 Name* name, | 6632 Name* name, |
6619 SimpleTransitionFlag simple_flag) { | 6633 SimpleTransitionFlag simple_flag) { |
6620 ASSERT(descriptors->IsSortedNoDuplicates()); | 6634 ASSERT(descriptors->IsSortedNoDuplicates()); |
6621 | 6635 |
6622 Map* result; | 6636 Map* result; |
6623 MaybeObject* maybe_result = CopyDropDescriptors(); | 6637 MaybeObject* maybe_result = CopyDropDescriptors(); |
6624 if (!maybe_result->To(&result)) return maybe_result; | 6638 if (!maybe_result->To(&result)) return maybe_result; |
6625 | 6639 |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6859 | 6873 |
6860 // We replace the key if it is already present. | 6874 // We replace the key if it is already present. |
6861 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 6875 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
6862 if (index != DescriptorArray::kNotFound) { | 6876 if (index != DescriptorArray::kNotFound) { |
6863 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); | 6877 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); |
6864 } | 6878 } |
6865 return CopyAddDescriptor(descriptor, flag); | 6879 return CopyAddDescriptor(descriptor, flag); |
6866 } | 6880 } |
6867 | 6881 |
6868 | 6882 |
| 6883 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( |
| 6884 Handle<DescriptorArray> desc, |
| 6885 int enumeration_index, |
| 6886 PropertyAttributes attributes) { |
| 6887 CALL_HEAP_FUNCTION(desc->GetIsolate(), |
| 6888 desc->CopyUpToAddAttributes(enumeration_index, attributes), |
| 6889 DescriptorArray); |
| 6890 } |
| 6891 |
| 6892 |
6869 MaybeObject* DescriptorArray::CopyUpToAddAttributes( | 6893 MaybeObject* DescriptorArray::CopyUpToAddAttributes( |
6870 int enumeration_index, PropertyAttributes attributes) { | 6894 int enumeration_index, PropertyAttributes attributes) { |
6871 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | 6895 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
6872 | 6896 |
6873 int size = enumeration_index; | 6897 int size = enumeration_index; |
6874 | 6898 |
6875 DescriptorArray* descriptors; | 6899 DescriptorArray* descriptors; |
6876 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size); | 6900 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size); |
6877 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 6901 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
6878 DescriptorArray::WhitenessWitness witness(descriptors); | 6902 DescriptorArray::WhitenessWitness witness(descriptors); |
(...skipping 9246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16125 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16149 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16126 static const char* error_messages_[] = { | 16150 static const char* error_messages_[] = { |
16127 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16151 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16128 }; | 16152 }; |
16129 #undef ERROR_MESSAGES_TEXTS | 16153 #undef ERROR_MESSAGES_TEXTS |
16130 return error_messages_[reason]; | 16154 return error_messages_[reason]; |
16131 } | 16155 } |
16132 | 16156 |
16133 | 16157 |
16134 } } // namespace v8::internal | 16158 } } // namespace v8::internal |
OLD | NEW |