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 |