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