diff options
Diffstat (limited to 'V8Binding/v8/src/stub-cache.cc')
-rw-r--r-- | V8Binding/v8/src/stub-cache.cc | 150 |
1 files changed, 115 insertions, 35 deletions
diff --git a/V8Binding/v8/src/stub-cache.cc b/V8Binding/v8/src/stub-cache.cc index 7ca2677..b25f5b4 100644 --- a/V8Binding/v8/src/stub-cache.cc +++ b/V8Binding/v8/src/stub-cache.cc @@ -736,22 +736,22 @@ Handle<Code> ComputeCallMiss(int argc) { Object* LoadCallbackProperty(Arguments args) { Handle<JSObject> recv = args.at<JSObject>(0); - AccessorInfo* callback = AccessorInfo::cast(args[1]); + Handle<JSObject> holder = args.at<JSObject>(1); + AccessorInfo* callback = AccessorInfo::cast(args[2]); + Handle<Object> data = args.at<Object>(3); Address getter_address = v8::ToCData<Address>(callback->getter()); v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); ASSERT(fun != NULL); - Handle<String> name = args.at<String>(2); - Handle<JSObject> holder = args.at<JSObject>(3); - HandleScope scope; - Handle<Object> data(callback->data()); - LOG(ApiNamedPropertyAccess("load", *recv, *name)); + Handle<String> name = args.at<String>(4); // NOTE: If we can align the structure of an AccessorInfo with the // locations of the arguments to this function maybe we don't have // to explicitly create the structure but can just pass a pointer // into the stack. + LOG(ApiNamedPropertyAccess("load", *recv, *name)); v8::AccessorInfo info(v8::Utils::ToLocal(recv), v8::Utils::ToLocal(data), v8::Utils::ToLocal(holder)); + HandleScope scope; v8::Handle<v8::Value> result; { // Leaving JavaScript. @@ -787,49 +787,129 @@ Object* StoreCallbackProperty(Arguments args) { return *value; } +/** + * Attempts to load a property with an interceptor (which must be present), + * but doesn't search the prototype chain. + * + * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't + * provide any value for the given name. + */ +Object* LoadPropertyWithInterceptorOnly(Arguments args) { + Handle<JSObject> receiver_handle = args.at<JSObject>(0); + Handle<JSObject> holder_handle = args.at<JSObject>(1); + Handle<String> name_handle = args.at<String>(2); + Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3); + Handle<Object> data_handle = args.at<Object>(4); + + Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); + v8::NamedPropertyGetter getter = + FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address); + ASSERT(getter != NULL); -Object* LoadInterceptorProperty(Arguments args) { - JSObject* recv = JSObject::cast(args[0]); - JSObject* holder = JSObject::cast(args[1]); - String* name = String::cast(args[2]); - Smi* lookup_hint = Smi::cast(args[3]); - ASSERT(holder->HasNamedInterceptor()); - PropertyAttributes attr = NONE; - - Object* result = holder->GetInterceptorPropertyWithLookupHint( - recv, lookup_hint, name, &attr); - if (result->IsFailure()) return result; + { + // Use the interceptor getter. + v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), + v8::Utils::ToLocal(data_handle), + v8::Utils::ToLocal(holder_handle)); + HandleScope scope; + v8::Handle<v8::Value> r; + { + // Leaving JavaScript. + VMState state(EXTERNAL); + r = getter(v8::Utils::ToLocal(name_handle), info); + } + RETURN_IF_SCHEDULED_EXCEPTION(); + if (!r.IsEmpty()) { + return *v8::Utils::OpenHandle(*r); + } + } - // If the property is present, return it. - if (attr != ABSENT) return result; + return Heap::no_interceptor_result_sentinel(); +} - // If the top frame is an internal frame, this is really a call - // IC. In this case, we simply return the undefined result which - // will lead to an exception when trying to invoke the result as a - // function. - StackFrameIterator it; - it.Advance(); // skip exit frame - if (it.frame()->is_internal()) return result; +static Object* ThrowReferenceError(String* name) { // If the load is non-contextual, just return the undefined result. // Note that both keyed and non-keyed loads may end up here, so we // can't use either LoadIC or KeyedLoadIC constructors. IC ic(IC::NO_EXTRA_FRAME); ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub()); - if (!ic.is_contextual()) return result; + if (!ic.is_contextual()) return Heap::undefined_value(); // Throw a reference error. + HandleScope scope; + Handle<String> name_handle(name); + Handle<Object> error = + Factory::NewReferenceError("not_defined", + HandleVector(&name_handle, 1)); + return Top::Throw(*error); +} + + +static Object* LoadWithInterceptor(Arguments* args, + PropertyAttributes* attrs) { + Handle<JSObject> receiver_handle = args->at<JSObject>(0); + Handle<JSObject> holder_handle = args->at<JSObject>(1); + Handle<String> name_handle = args->at<String>(2); + Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(3); + Handle<Object> data_handle = args->at<Object>(4); + + Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); + v8::NamedPropertyGetter getter = + FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address); + ASSERT(getter != NULL); + { + // Use the interceptor getter. + v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), + v8::Utils::ToLocal(data_handle), + v8::Utils::ToLocal(holder_handle)); HandleScope scope; - // We cannot use the raw name pointer here since getting the - // property might cause a GC. However, we can get the name from - // the stack using the arguments object. - Handle<String> name_handle = args.at<String>(2); - Handle<Object> error = - Factory::NewReferenceError("not_defined", - HandleVector(&name_handle, 1)); - return Top::Throw(*error); + v8::Handle<v8::Value> r; + { + // Leaving JavaScript. + VMState state(EXTERNAL); + r = getter(v8::Utils::ToLocal(name_handle), info); + } + RETURN_IF_SCHEDULED_EXCEPTION(); + if (!r.IsEmpty()) { + *attrs = NONE; + return *v8::Utils::OpenHandle(*r); + } } + + Object* result = holder_handle->GetPropertyPostInterceptor( + *receiver_handle, + *name_handle, + attrs); + RETURN_IF_SCHEDULED_EXCEPTION(); + return result; +} + + +/** + * Loads a property with an interceptor performing post interceptor + * lookup if interceptor failed. + */ +Object* LoadPropertyWithInterceptorForLoad(Arguments args) { + PropertyAttributes attr = NONE; + Object* result = LoadWithInterceptor(&args, &attr); + if (result->IsFailure()) return result; + + // If the property is present, return it. + if (attr != ABSENT) return result; + return ThrowReferenceError(String::cast(args[2])); +} + + +Object* LoadPropertyWithInterceptorForCall(Arguments args) { + PropertyAttributes attr; + Object* result = LoadWithInterceptor(&args, &attr); + RETURN_IF_SCHEDULED_EXCEPTION(); + // This is call IC. In this case, we simply return the undefined result which + // will lead to an exception when trying to invoke the result as a + // function. + return result; } |