OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "src/field-index.h" | 21 #include "src/field-index.h" |
22 #include "src/full-codegen.h" | 22 #include "src/full-codegen.h" |
23 #include "src/hydrogen.h" | 23 #include "src/hydrogen.h" |
24 #include "src/isolate-inl.h" | 24 #include "src/isolate-inl.h" |
25 #include "src/log.h" | 25 #include "src/log.h" |
26 #include "src/lookup.h" | 26 #include "src/lookup.h" |
27 #include "src/macro-assembler.h" | 27 #include "src/macro-assembler.h" |
28 #include "src/mark-compact.h" | 28 #include "src/mark-compact.h" |
29 #include "src/objects-inl.h" | 29 #include "src/objects-inl.h" |
30 #include "src/objects-visiting-inl.h" | 30 #include "src/objects-visiting-inl.h" |
| 31 #include "src/prototype.h" |
31 #include "src/safepoint-table.h" | 32 #include "src/safepoint-table.h" |
32 #include "src/string-search.h" | 33 #include "src/string-search.h" |
33 #include "src/string-stream.h" | 34 #include "src/string-stream.h" |
34 #include "src/utils.h" | 35 #include "src/utils.h" |
35 | 36 |
36 #ifdef ENABLE_DISASSEMBLER | 37 #ifdef ENABLE_DISASSEMBLER |
37 #include "src/disasm.h" | 38 #include "src/disasm.h" |
38 #include "src/disassembler.h" | 39 #include "src/disassembler.h" |
39 #endif | 40 #endif |
40 | 41 |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 return map() != fun->initial_map() | 795 return map() != fun->initial_map() |
795 || !HasFastObjectElements() | 796 || !HasFastObjectElements() |
796 || !HasFastProperties(); | 797 || !HasFastProperties(); |
797 } | 798 } |
798 | 799 |
799 | 800 |
800 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, | 801 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, |
801 Handle<Object> object, | 802 Handle<Object> object, |
802 Handle<Object> receiver, | 803 Handle<Object> receiver, |
803 uint32_t index) { | 804 uint32_t index) { |
804 Handle<Object> holder; | 805 if (object->IsUndefined()) { |
| 806 // TODO(verwaest): Why is this check here? |
| 807 UNREACHABLE(); |
| 808 return isolate->factory()->undefined_value(); |
| 809 } |
805 | 810 |
806 // Iterate up the prototype chain until an element is found or the null | 811 // Iterate up the prototype chain until an element is found or the null |
807 // prototype is encountered. | 812 // prototype is encountered. |
808 for (holder = object; | 813 for (PrototypeIterator iter(isolate, object, |
809 !holder->IsNull(); | 814 object->IsJSProxy() || object->IsJSObject() |
810 holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) { | 815 ? PrototypeIterator::START_AT_RECEIVER |
811 if (!holder->IsJSObject()) { | 816 : PrototypeIterator::START_AT_PROTOTYPE); |
812 if (holder->IsJSProxy()) { | 817 !iter.IsAtEnd(); iter.Advance()) { |
813 return JSProxy::GetElementWithHandler( | 818 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
814 Handle<JSProxy>::cast(holder), receiver, index); | 819 return JSProxy::GetElementWithHandler( |
815 } else if (holder->IsUndefined()) { | 820 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
816 // Undefined has no indexed properties. | 821 index); |
817 return isolate->factory()->undefined_value(); | |
818 } else { | |
819 holder = Handle<Object>(holder->GetPrototype(isolate), isolate); | |
820 ASSERT(holder->IsJSObject()); | |
821 } | |
822 } | 822 } |
823 | 823 |
824 // Inline the case for JSObjects. Doing so significantly improves the | 824 // Inline the case for JSObjects. Doing so significantly improves the |
825 // performance of fetching elements where checking the prototype chain is | 825 // performance of fetching elements where checking the prototype chain is |
826 // necessary. | 826 // necessary. |
827 Handle<JSObject> js_object = Handle<JSObject>::cast(holder); | 827 Handle<JSObject> js_object = |
| 828 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
828 | 829 |
829 // Check access rights if needed. | 830 // Check access rights if needed. |
830 if (js_object->IsAccessCheckNeeded()) { | 831 if (js_object->IsAccessCheckNeeded()) { |
831 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) { | 832 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) { |
832 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET); | 833 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET); |
833 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 834 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
834 return isolate->factory()->undefined_value(); | 835 return isolate->factory()->undefined_value(); |
835 } | 836 } |
836 } | 837 } |
837 | 838 |
838 if (js_object->HasIndexedInterceptor()) { | 839 if (js_object->HasIndexedInterceptor()) { |
839 return JSObject::GetElementWithInterceptor(js_object, receiver, index); | 840 return JSObject::GetElementWithInterceptor(js_object, receiver, index); |
840 } | 841 } |
841 | 842 |
842 if (js_object->elements() != isolate->heap()->empty_fixed_array()) { | 843 if (js_object->elements() != isolate->heap()->empty_fixed_array()) { |
843 Handle<Object> result; | 844 Handle<Object> result; |
844 ASSIGN_RETURN_ON_EXCEPTION( | 845 ASSIGN_RETURN_ON_EXCEPTION( |
845 isolate, result, | 846 isolate, result, |
846 js_object->GetElementsAccessor()->Get(receiver, js_object, index), | 847 js_object->GetElementsAccessor()->Get(receiver, js_object, index), |
847 Object); | 848 Object); |
848 if (!result->IsTheHole()) return result; | 849 if (!result->IsTheHole()) return result; |
849 } | 850 } |
850 } | 851 } |
851 | 852 |
852 return isolate->factory()->undefined_value(); | 853 return isolate->factory()->undefined_value(); |
853 } | 854 } |
854 | 855 |
855 | 856 |
856 Object* Object::GetPrototype(Isolate* isolate) { | 857 Map* Object::GetRootMap(Isolate* isolate) { |
857 DisallowHeapAllocation no_alloc; | 858 DisallowHeapAllocation no_alloc; |
858 if (IsSmi()) { | 859 if (IsSmi()) { |
859 Context* context = isolate->context()->native_context(); | 860 Context* context = isolate->context()->native_context(); |
860 return context->number_function()->instance_prototype(); | 861 return context->number_function()->initial_map(); |
861 } | 862 } |
862 | 863 |
863 HeapObject* heap_object = HeapObject::cast(this); | 864 HeapObject* heap_object = HeapObject::cast(this); |
864 | 865 |
865 // The object is either a number, a string, a boolean, | 866 // The object is either a number, a string, a boolean, |
866 // a real JS object, or a Harmony proxy. | 867 // a real JS object, or a Harmony proxy. |
867 if (heap_object->IsJSReceiver()) { | 868 if (heap_object->IsJSReceiver()) { |
868 return heap_object->map()->prototype(); | 869 return heap_object->map(); |
869 } | 870 } |
870 Context* context = isolate->context()->native_context(); | 871 Context* context = isolate->context()->native_context(); |
871 | 872 |
872 if (heap_object->IsHeapNumber()) { | 873 if (heap_object->IsHeapNumber()) { |
873 return context->number_function()->instance_prototype(); | 874 return context->number_function()->initial_map(); |
874 } | 875 } |
875 if (heap_object->IsString()) { | 876 if (heap_object->IsString()) { |
876 return context->string_function()->instance_prototype(); | 877 return context->string_function()->initial_map(); |
877 } | 878 } |
878 if (heap_object->IsSymbol()) { | 879 if (heap_object->IsSymbol()) { |
879 return context->symbol_function()->instance_prototype(); | 880 return context->symbol_function()->initial_map(); |
880 } | 881 } |
881 if (heap_object->IsBoolean()) { | 882 if (heap_object->IsBoolean()) { |
882 return context->boolean_function()->instance_prototype(); | 883 return context->boolean_function()->initial_map(); |
883 } else { | |
884 return isolate->heap()->null_value(); | |
885 } | 884 } |
| 885 return isolate->heap()->null_value()->map(); |
886 } | 886 } |
887 | 887 |
888 | 888 |
889 Handle<Object> Object::GetPrototype(Isolate* isolate, | |
890 Handle<Object> object) { | |
891 return handle(object->GetPrototype(isolate), isolate); | |
892 } | |
893 | |
894 | |
895 Object* Object::GetHash() { | 889 Object* Object::GetHash() { |
896 // The object is either a number, a name, an odd-ball, | 890 // The object is either a number, a name, an odd-ball, |
897 // a real JS object, or a Harmony proxy. | 891 // a real JS object, or a Harmony proxy. |
898 if (IsNumber()) { | 892 if (IsNumber()) { |
899 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); | 893 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); |
900 return Smi::FromInt(hash & Smi::kMaxValue); | 894 return Smi::FromInt(hash & Smi::kMaxValue); |
901 } | 895 } |
902 if (IsName()) { | 896 if (IsName()) { |
903 uint32_t hash = Name::cast(this)->Hash(); | 897 uint32_t hash = Name::cast(this)->Hash(); |
904 return Smi::FromInt(hash); | 898 return Smi::FromInt(hash); |
(...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3021 } | 3015 } |
3022 | 3016 |
3023 | 3017 |
3024 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( | 3018 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( |
3025 Handle<JSObject> object, | 3019 Handle<JSObject> object, |
3026 uint32_t index, | 3020 uint32_t index, |
3027 Handle<Object> value, | 3021 Handle<Object> value, |
3028 bool* found, | 3022 bool* found, |
3029 StrictMode strict_mode) { | 3023 StrictMode strict_mode) { |
3030 Isolate *isolate = object->GetIsolate(); | 3024 Isolate *isolate = object->GetIsolate(); |
3031 for (Handle<Object> proto = handle(object->GetPrototype(), isolate); | 3025 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd(); |
3032 !proto->IsNull(); | 3026 iter.Advance()) { |
3033 proto = handle(proto->GetPrototype(isolate), isolate)) { | 3027 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
3034 if (proto->IsJSProxy()) { | |
3035 return JSProxy::SetPropertyViaPrototypesWithHandler( | 3028 return JSProxy::SetPropertyViaPrototypesWithHandler( |
3036 Handle<JSProxy>::cast(proto), | 3029 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object, |
3037 object, | |
3038 isolate->factory()->Uint32ToString(index), // name | 3030 isolate->factory()->Uint32ToString(index), // name |
3039 value, | 3031 value, NONE, strict_mode, found); |
3040 NONE, | |
3041 strict_mode, | |
3042 found); | |
3043 } | 3032 } |
3044 Handle<JSObject> js_proto = Handle<JSObject>::cast(proto); | 3033 Handle<JSObject> js_proto = |
| 3034 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
3045 if (!js_proto->HasDictionaryElements()) { | 3035 if (!js_proto->HasDictionaryElements()) { |
3046 continue; | 3036 continue; |
3047 } | 3037 } |
3048 Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary()); | 3038 Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary()); |
3049 int entry = dictionary->FindEntry(index); | 3039 int entry = dictionary->FindEntry(index); |
3050 if (entry != SeededNumberDictionary::kNotFound) { | 3040 if (entry != SeededNumberDictionary::kNotFound) { |
3051 PropertyDetails details = dictionary->DetailsAt(entry); | 3041 PropertyDetails details = dictionary->DetailsAt(entry); |
3052 if (details.type() == CALLBACKS) { | 3042 if (details.type() == CALLBACKS) { |
3053 *found = true; | 3043 *found = true; |
3054 Handle<Object> structure(dictionary->ValueAt(entry), isolate); | 3044 Handle<Object> structure(dictionary->ValueAt(entry), isolate); |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3512 if (result->IsFound()) return; | 3502 if (result->IsFound()) return; |
3513 | 3503 |
3514 LookupRealNamedPropertyInPrototypes(name, result); | 3504 LookupRealNamedPropertyInPrototypes(name, result); |
3515 } | 3505 } |
3516 | 3506 |
3517 | 3507 |
3518 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, | 3508 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, |
3519 LookupResult* result) { | 3509 LookupResult* result) { |
3520 DisallowHeapAllocation no_gc; | 3510 DisallowHeapAllocation no_gc; |
3521 Isolate* isolate = GetIsolate(); | 3511 Isolate* isolate = GetIsolate(); |
3522 Heap* heap = isolate->heap(); | 3512 for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) { |
3523 for (Object* pt = GetPrototype(); | 3513 if (iter.GetCurrent()->IsJSProxy()) { |
3524 pt != heap->null_value(); | 3514 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); |
3525 pt = pt->GetPrototype(isolate)) { | |
3526 if (pt->IsJSProxy()) { | |
3527 return result->HandlerResult(JSProxy::cast(pt)); | |
3528 } | 3515 } |
3529 JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result); | 3516 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); |
3530 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 3517 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |
3531 if (result->IsFound()) return; | 3518 if (result->IsFound()) return; |
3532 } | 3519 } |
3533 result->NotFound(); | 3520 result->NotFound(); |
3534 } | 3521 } |
3535 | 3522 |
3536 | 3523 |
3537 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 3524 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
3538 LookupResult* result, | 3525 LookupResult* result, |
3539 Handle<Name> key, | 3526 Handle<Name> key, |
(...skipping 2822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6362 | 6349 |
6363 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 6350 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
6364 KeyCollectionType type) { | 6351 KeyCollectionType type) { |
6365 USE(ContainsOnlyValidKeys); | 6352 USE(ContainsOnlyValidKeys); |
6366 Isolate* isolate = object->GetIsolate(); | 6353 Isolate* isolate = object->GetIsolate(); |
6367 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); | 6354 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); |
6368 Handle<JSFunction> arguments_function( | 6355 Handle<JSFunction> arguments_function( |
6369 JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); | 6356 JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); |
6370 | 6357 |
6371 // Only collect keys if access is permitted. | 6358 // Only collect keys if access is permitted. |
6372 for (Handle<Object> p = object; | 6359 for (PrototypeIterator iter(isolate, object, |
6373 *p != isolate->heap()->null_value(); | 6360 PrototypeIterator::START_AT_RECEIVER); |
6374 p = Handle<Object>(p->GetPrototype(isolate), isolate)) { | 6361 !iter.IsAtEnd(); iter.Advance()) { |
6375 if (p->IsJSProxy()) { | 6362 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
6376 Handle<JSProxy> proxy(JSProxy::cast(*p), isolate); | 6363 Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)), |
| 6364 isolate); |
6377 Handle<Object> args[] = { proxy }; | 6365 Handle<Object> args[] = { proxy }; |
6378 Handle<Object> names; | 6366 Handle<Object> names; |
6379 ASSIGN_RETURN_ON_EXCEPTION( | 6367 ASSIGN_RETURN_ON_EXCEPTION( |
6380 isolate, names, | 6368 isolate, names, |
6381 Execution::Call(isolate, | 6369 Execution::Call(isolate, |
6382 isolate->proxy_enumerate(), | 6370 isolate->proxy_enumerate(), |
6383 object, | 6371 object, |
6384 ARRAY_SIZE(args), | 6372 ARRAY_SIZE(args), |
6385 args), | 6373 args), |
6386 FixedArray); | 6374 FixedArray); |
6387 ASSIGN_RETURN_ON_EXCEPTION( | 6375 ASSIGN_RETURN_ON_EXCEPTION( |
6388 isolate, content, | 6376 isolate, content, |
6389 FixedArray::AddKeysFromArrayLike( | 6377 FixedArray::AddKeysFromArrayLike( |
6390 content, Handle<JSObject>::cast(names)), | 6378 content, Handle<JSObject>::cast(names)), |
6391 FixedArray); | 6379 FixedArray); |
6392 break; | 6380 break; |
6393 } | 6381 } |
6394 | 6382 |
6395 Handle<JSObject> current(JSObject::cast(*p), isolate); | 6383 Handle<JSObject> current = |
| 6384 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
6396 | 6385 |
6397 // Check access rights if required. | 6386 // Check access rights if required. |
6398 if (current->IsAccessCheckNeeded() && | 6387 if (current->IsAccessCheckNeeded() && |
6399 !isolate->MayNamedAccess( | 6388 !isolate->MayNamedAccess( |
6400 current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { | 6389 current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { |
6401 isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS); | 6390 isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS); |
6402 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | 6391 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); |
6403 break; | 6392 break; |
6404 } | 6393 } |
6405 | 6394 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6603 } | 6592 } |
6604 | 6593 |
6605 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); | 6594 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); |
6606 accessors->SetComponents(*getter, *setter); | 6595 accessors->SetComponents(*getter, *setter); |
6607 | 6596 |
6608 SetPropertyCallback(object, name, accessors, attributes); | 6597 SetPropertyCallback(object, name, accessors, attributes); |
6609 } | 6598 } |
6610 | 6599 |
6611 | 6600 |
6612 bool Map::DictionaryElementsInPrototypeChainOnly() { | 6601 bool Map::DictionaryElementsInPrototypeChainOnly() { |
6613 Heap* heap = GetHeap(); | |
6614 | |
6615 if (IsDictionaryElementsKind(elements_kind())) { | 6602 if (IsDictionaryElementsKind(elements_kind())) { |
6616 return false; | 6603 return false; |
6617 } | 6604 } |
6618 | 6605 |
6619 for (Object* prototype = this->prototype(); | 6606 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { |
6620 prototype != heap->null_value(); | 6607 if (iter.GetCurrent()->IsJSProxy()) { |
6621 prototype = prototype->GetPrototype(GetIsolate())) { | |
6622 if (prototype->IsJSProxy()) { | |
6623 // Be conservative, don't walk into proxies. | 6608 // Be conservative, don't walk into proxies. |
6624 return true; | 6609 return true; |
6625 } | 6610 } |
6626 | 6611 |
6627 if (IsDictionaryElementsKind( | 6612 if (IsDictionaryElementsKind( |
6628 JSObject::cast(prototype)->map()->elements_kind())) { | 6613 JSObject::cast(iter.GetCurrent())->map()->elements_kind())) { |
6629 return true; | 6614 return true; |
6630 } | 6615 } |
6631 } | 6616 } |
6632 | 6617 |
6633 return false; | 6618 return false; |
6634 } | 6619 } |
6635 | 6620 |
6636 | 6621 |
6637 void JSObject::SetElementCallback(Handle<JSObject> object, | 6622 void JSObject::SetElementCallback(Handle<JSObject> object, |
6638 uint32_t index, | 6623 uint32_t index, |
(...skipping 3480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10119 instance_type = JS_OBJECT_TYPE; | 10104 instance_type = JS_OBJECT_TYPE; |
10120 instance_size = function->shared()->CalculateInstanceSize(); | 10105 instance_size = function->shared()->CalculateInstanceSize(); |
10121 in_object_properties = function->shared()->CalculateInObjectProperties(); | 10106 in_object_properties = function->shared()->CalculateInObjectProperties(); |
10122 } | 10107 } |
10123 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size); | 10108 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size); |
10124 | 10109 |
10125 // Fetch or allocate prototype. | 10110 // Fetch or allocate prototype. |
10126 Handle<Object> prototype; | 10111 Handle<Object> prototype; |
10127 if (function->has_instance_prototype()) { | 10112 if (function->has_instance_prototype()) { |
10128 prototype = handle(function->instance_prototype(), isolate); | 10113 prototype = handle(function->instance_prototype(), isolate); |
10129 for (Handle<Object> p = prototype; !p->IsNull() && !p->IsJSProxy(); | 10114 for (PrototypeIterator iter(isolate, prototype, |
10130 p = Object::GetPrototype(isolate, p)) { | 10115 PrototypeIterator::START_AT_RECEIVER); |
10131 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(p)); | 10116 !iter.IsAtEnd(); iter.Advance()) { |
| 10117 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| 10118 break; |
| 10119 } |
| 10120 JSObject::OptimizeAsPrototype( |
| 10121 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
10132 } | 10122 } |
10133 } else { | 10123 } else { |
10134 prototype = isolate->factory()->NewFunctionPrototype(function); | 10124 prototype = isolate->factory()->NewFunctionPrototype(function); |
10135 } | 10125 } |
10136 map->set_inobject_properties(in_object_properties); | 10126 map->set_inobject_properties(in_object_properties); |
10137 map->set_unused_property_fields(in_object_properties); | 10127 map->set_unused_property_fields(in_object_properties); |
10138 map->set_prototype(*prototype); | 10128 map->set_prototype(*prototype); |
10139 ASSERT(map->has_fast_object_elements()); | 10129 ASSERT(map->has_fast_object_elements()); |
10140 | 10130 |
10141 // Finally link initial map and constructor function. | 10131 // Finally link initial map and constructor function. |
(...skipping 2049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12191 Handle<Object> args[] = { object }; | 12181 Handle<Object> args[] = { object }; |
12192 Handle<Object> error = isolate->factory()->NewTypeError( | 12182 Handle<Object> error = isolate->factory()->NewTypeError( |
12193 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); | 12183 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); |
12194 return isolate->Throw<Object>(error); | 12184 return isolate->Throw<Object>(error); |
12195 } | 12185 } |
12196 | 12186 |
12197 // Before we can set the prototype we need to be sure | 12187 // Before we can set the prototype we need to be sure |
12198 // prototype cycles are prevented. | 12188 // prototype cycles are prevented. |
12199 // It is sufficient to validate that the receiver is not in the new prototype | 12189 // It is sufficient to validate that the receiver is not in the new prototype |
12200 // chain. | 12190 // chain. |
12201 for (Object* pt = *value; | 12191 for (PrototypeIterator iter(isolate, *value, |
12202 pt != heap->null_value(); | 12192 PrototypeIterator::START_AT_RECEIVER); |
12203 pt = pt->GetPrototype(isolate)) { | 12193 !iter.IsAtEnd(); iter.Advance()) { |
12204 if (JSReceiver::cast(pt) == *object) { | 12194 if (JSReceiver::cast(iter.GetCurrent()) == *object) { |
12205 // Cycle detected. | 12195 // Cycle detected. |
12206 Handle<Object> error = isolate->factory()->NewError( | 12196 Handle<Object> error = isolate->factory()->NewError( |
12207 "cyclic_proto", HandleVector<Object>(NULL, 0)); | 12197 "cyclic_proto", HandleVector<Object>(NULL, 0)); |
12208 return isolate->Throw<Object>(error); | 12198 return isolate->Throw<Object>(error); |
12209 } | 12199 } |
12210 } | 12200 } |
12211 | 12201 |
12212 bool dictionary_elements_in_chain = | 12202 bool dictionary_elements_in_chain = |
12213 object->map()->DictionaryElementsInPrototypeChainOnly(); | 12203 object->map()->DictionaryElementsInPrototypeChainOnly(); |
12214 Handle<JSObject> real_receiver = object; | 12204 Handle<JSObject> real_receiver = object; |
12215 | 12205 |
12216 if (skip_hidden_prototypes) { | 12206 if (skip_hidden_prototypes) { |
12217 // Find the first object in the chain whose prototype object is not | 12207 // Find the first object in the chain whose prototype object is not |
12218 // hidden and set the new prototype on that object. | 12208 // hidden and set the new prototype on that object. |
12219 Object* current_proto = real_receiver->GetPrototype(); | 12209 PrototypeIterator iter(isolate, real_receiver); |
12220 while (current_proto->IsJSObject() && | 12210 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
12221 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { | 12211 real_receiver = |
12222 real_receiver = handle(JSObject::cast(current_proto), isolate); | 12212 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
12223 current_proto = current_proto->GetPrototype(isolate); | 12213 iter.Advance(); |
12224 } | 12214 } |
12225 } | 12215 } |
12226 | 12216 |
12227 // Set the new prototype of the object. | 12217 // Set the new prototype of the object. |
12228 Handle<Map> map(real_receiver->map()); | 12218 Handle<Map> map(real_receiver->map()); |
12229 | 12219 |
12230 // Nothing to do if prototype is already set. | 12220 // Nothing to do if prototype is already set. |
12231 if (map->prototype() == *value) return value; | 12221 if (map->prototype() == *value) return value; |
12232 | 12222 |
12233 if (value->IsJSObject()) { | 12223 if (value->IsJSObject()) { |
(...skipping 4761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16995 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16985 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16996 static const char* error_messages_[] = { | 16986 static const char* error_messages_[] = { |
16997 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16987 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16998 }; | 16988 }; |
16999 #undef ERROR_MESSAGES_TEXTS | 16989 #undef ERROR_MESSAGES_TEXTS |
17000 return error_messages_[reason]; | 16990 return error_messages_[reason]; |
17001 } | 16991 } |
17002 | 16992 |
17003 | 16993 |
17004 } } // namespace v8::internal | 16994 } } // namespace v8::internal |
OLD | NEW |