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