| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/ic/ic.h" | 5 #include "src/ic/ic.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/api-arguments.h" | 9 #include "src/api-arguments.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 1404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 switch (it->state()) { | 1415 switch (it->state()) { |
| 1416 case LookupIterator::NOT_FOUND: | 1416 case LookupIterator::NOT_FOUND: |
| 1417 case LookupIterator::TRANSITION: | 1417 case LookupIterator::TRANSITION: |
| 1418 UNREACHABLE(); | 1418 UNREACHABLE(); |
| 1419 case LookupIterator::JSPROXY: | 1419 case LookupIterator::JSPROXY: |
| 1420 return false; | 1420 return false; |
| 1421 case LookupIterator::INTERCEPTOR: { | 1421 case LookupIterator::INTERCEPTOR: { |
| 1422 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1422 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
| 1423 InterceptorInfo* info = holder->GetNamedInterceptor(); | 1423 InterceptorInfo* info = holder->GetNamedInterceptor(); |
| 1424 if (it->HolderIsReceiverOrHiddenPrototype()) { | 1424 if (it->HolderIsReceiverOrHiddenPrototype()) { |
| 1425 if (!info->setter()->IsUndefined()) return true; | 1425 return !info->non_masking() && receiver.is_identical_to(holder) && |
| 1426 !info->setter()->IsUndefined(); |
| 1426 } else if (!info->getter()->IsUndefined() || | 1427 } else if (!info->getter()->IsUndefined() || |
| 1427 !info->query()->IsUndefined()) { | 1428 !info->query()->IsUndefined()) { |
| 1428 return false; | 1429 return false; |
| 1429 } | 1430 } |
| 1430 break; | 1431 break; |
| 1431 } | 1432 } |
| 1432 case LookupIterator::ACCESS_CHECK: | 1433 case LookupIterator::ACCESS_CHECK: |
| 1433 if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false; | 1434 if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false; |
| 1434 break; | 1435 break; |
| 1435 case LookupIterator::ACCESSOR: | 1436 case LookupIterator::ACCESSOR: |
| (...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2800 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, | 2801 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, |
| 2801 *holder, Object::DONT_THROW); | 2802 *holder, Object::DONT_THROW); |
| 2802 | 2803 |
| 2803 v8::GenericNamedPropertyGetterCallback getter = | 2804 v8::GenericNamedPropertyGetterCallback getter = |
| 2804 v8::ToCData<v8::GenericNamedPropertyGetterCallback>( | 2805 v8::ToCData<v8::GenericNamedPropertyGetterCallback>( |
| 2805 interceptor->getter()); | 2806 interceptor->getter()); |
| 2806 Handle<Object> result = arguments.Call(getter, name); | 2807 Handle<Object> result = arguments.Call(getter, name); |
| 2807 | 2808 |
| 2808 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 2809 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 2809 | 2810 |
| 2810 Handle<Object> result_internal; | 2811 if (!result.is_null()) return *result; |
| 2811 if (result.is_null()) { | 2812 return isolate->heap()->no_interceptor_result_sentinel(); |
| 2812 return isolate->heap()->no_interceptor_result_sentinel(); | |
| 2813 } | |
| 2814 return *result; | |
| 2815 } | 2813 } |
| 2816 | 2814 |
| 2817 | 2815 |
| 2818 /** | 2816 /** |
| 2819 * Loads a property with an interceptor performing post interceptor | 2817 * Loads a property with an interceptor performing post interceptor |
| 2820 * lookup if interceptor failed. | 2818 * lookup if interceptor failed. |
| 2821 */ | 2819 */ |
| 2822 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) { | 2820 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) { |
| 2823 HandleScope scope(isolate); | 2821 HandleScope scope(isolate); |
| 2824 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); | 2822 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |
| 2825 Handle<Name> name = | 2823 Handle<Name> name = |
| 2826 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); | 2824 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |
| 2827 Handle<JSObject> receiver = | 2825 Handle<JSObject> receiver = |
| 2828 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); | 2826 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |
| 2829 Handle<JSObject> holder = | 2827 Handle<JSObject> holder = |
| 2830 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); | 2828 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |
| 2831 | 2829 |
| 2832 Handle<Object> result; | 2830 InterceptorInfo* interceptor = holder->GetNamedInterceptor(); |
| 2831 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, |
| 2832 *holder, Object::DONT_THROW); |
| 2833 |
| 2834 v8::GenericNamedPropertyGetterCallback getter = |
| 2835 v8::ToCData<v8::GenericNamedPropertyGetterCallback>( |
| 2836 interceptor->getter()); |
| 2837 Handle<Object> result = arguments.Call(getter, name); |
| 2838 |
| 2839 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 2840 |
| 2841 if (!result.is_null()) return *result; |
| 2842 |
| 2833 LookupIterator it(receiver, name, holder); | 2843 LookupIterator it(receiver, name, holder); |
| 2834 // TODO(conradw): Investigate strong mode semantics for this. | 2844 // Skip any lookup work until we hit the (possibly non-masking) interceptor. |
| 2845 while (it.state() != LookupIterator::INTERCEPTOR || |
| 2846 !it.GetHolder<JSObject>().is_identical_to(holder)) { |
| 2847 DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess()); |
| 2848 it.Next(); |
| 2849 } |
| 2850 // Skip past the interceptor. |
| 2851 it.Next(); |
| 2835 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); | 2852 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); |
| 2836 | 2853 |
| 2837 if (it.IsFound()) return *result; | 2854 if (it.IsFound()) return *result; |
| 2838 | 2855 |
| 2839 // Return the undefined result if the reference error should not be thrown. | |
| 2840 // Note that both keyed and non-keyed loads may end up here. | |
| 2841 LoadICNexus nexus(isolate); | 2856 LoadICNexus nexus(isolate); |
| 2842 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2857 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2843 if (!ic.ShouldThrowReferenceError(it.GetReceiver())) { | 2858 if (!ic.ShouldThrowReferenceError(it.GetReceiver())) { |
| 2844 return isolate->heap()->undefined_value(); | 2859 return isolate->heap()->undefined_value(); |
| 2845 } | 2860 } |
| 2846 | 2861 |
| 2847 // Throw a reference error. | 2862 // Throw a reference error. |
| 2848 THROW_NEW_ERROR_RETURN_FAILURE( | 2863 THROW_NEW_ERROR_RETURN_FAILURE( |
| 2849 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name())); | 2864 isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name())); |
| 2850 } | 2865 } |
| 2851 | 2866 |
| 2852 | 2867 |
| 2853 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) { | 2868 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) { |
| 2854 HandleScope scope(isolate); | 2869 HandleScope scope(isolate); |
| 2855 DCHECK(args.length() == 3); | 2870 DCHECK(args.length() == 3); |
| 2856 StoreICNexus nexus(isolate); | 2871 StoreICNexus nexus(isolate); |
| 2857 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2872 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2858 Handle<JSObject> receiver = args.at<JSObject>(0); | 2873 Handle<JSObject> receiver = args.at<JSObject>(0); |
| 2859 Handle<Name> name = args.at<Name>(1); | 2874 Handle<Name> name = args.at<Name>(1); |
| 2860 Handle<Object> value = args.at<Object>(2); | 2875 Handle<Object> value = args.at<Object>(2); |
| 2861 #ifdef DEBUG | 2876 |
| 2862 PrototypeIterator iter(isolate, receiver, | 2877 DCHECK(receiver->HasNamedInterceptor()); |
| 2863 PrototypeIterator::START_AT_RECEIVER, | 2878 InterceptorInfo* interceptor = receiver->GetNamedInterceptor(); |
| 2864 PrototypeIterator::END_AT_NON_HIDDEN); | 2879 DCHECK(!interceptor->non_masking()); |
| 2865 bool found = false; | 2880 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, |
| 2866 for (; !iter.IsAtEnd(); iter.Advance()) { | 2881 *receiver, Object::DONT_THROW); |
| 2867 Handle<Object> current = PrototypeIterator::GetCurrent(iter); | 2882 |
| 2868 if (current->IsJSObject() && | 2883 v8::GenericNamedPropertySetterCallback setter = |
| 2869 Handle<JSObject>::cast(current)->HasNamedInterceptor()) { | 2884 v8::ToCData<v8::GenericNamedPropertySetterCallback>( |
| 2870 found = true; | 2885 interceptor->setter()); |
| 2871 break; | 2886 Handle<Object> result = arguments.Call(setter, name, value); |
| 2872 } | 2887 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| 2888 if (!result.is_null()) return *value; |
| 2889 |
| 2890 LookupIterator it(receiver, name, receiver); |
| 2891 // Skip past any access check on the receiver. |
| 2892 if (it.state() == LookupIterator::ACCESS_CHECK) { |
| 2893 DCHECK(it.HasAccess()); |
| 2894 it.Next(); |
| 2873 } | 2895 } |
| 2874 DCHECK(found); | 2896 // Skip past the interceptor on the receiver. |
| 2875 #endif | 2897 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
| 2876 Handle<Object> result; | 2898 it.Next(); |
| 2877 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2899 |
| 2878 isolate, result, | 2900 MAYBE_RETURN(Object::SetProperty(&it, value, ic.language_mode(), |
| 2879 JSObject::SetProperty(receiver, name, value, ic.language_mode())); | 2901 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED), |
| 2880 return *result; | 2902 isolate->heap()->exception()); |
| 2903 return *value; |
| 2881 } | 2904 } |
| 2882 | 2905 |
| 2883 | 2906 |
| 2884 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) { | 2907 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) { |
| 2885 // TODO(verwaest): This should probably get the holder and receiver as input. | 2908 // TODO(verwaest): This should probably get the holder and receiver as input. |
| 2886 HandleScope scope(isolate); | 2909 HandleScope scope(isolate); |
| 2887 Handle<JSObject> receiver = args.at<JSObject>(0); | 2910 Handle<JSObject> receiver = args.at<JSObject>(0); |
| 2888 DCHECK(args.smi_at(1) >= 0); | 2911 DCHECK(args.smi_at(1) >= 0); |
| 2889 uint32_t index = args.smi_at(1); | 2912 uint32_t index = args.smi_at(1); |
| 2890 | 2913 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2936 KeyedLoadICNexus nexus(vector, vector_slot); | 2959 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2937 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2960 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2938 ic.UpdateState(receiver, key); | 2961 ic.UpdateState(receiver, key); |
| 2939 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2962 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2940 } | 2963 } |
| 2941 | 2964 |
| 2942 return *result; | 2965 return *result; |
| 2943 } | 2966 } |
| 2944 } // namespace internal | 2967 } // namespace internal |
| 2945 } // namespace v8 | 2968 } // namespace v8 |
| OLD | NEW |