| 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 |