Index: src/stub-cache.cc |
=================================================================== |
--- src/stub-cache.cc (revision 2562) |
+++ src/stub-cache.cc (working copy) |
@@ -787,23 +787,25 @@ |
return *value; |
} |
- |
-Object* LoadInterceptorProperty(Arguments args) { |
+/** |
+ * 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); |
- Smi* lookup_hint = Smi::cast(args[3]); |
- Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(4); |
- Handle<Object> data_handle = args.at<Object>(5); |
+ 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); |
- PropertyAttributes attributes = ABSENT; |
- Object* result = Heap::undefined_value(); |
- |
{ |
// Use the interceptor getter. |
v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), |
@@ -822,68 +824,95 @@ |
} |
} |
- int property_index = lookup_hint->value(); |
- if (property_index >= 0) { |
- result = holder_handle->FastPropertyAt(property_index); |
- } else { |
- switch (property_index) { |
- case JSObject::kLookupInPrototype: { |
- Object* pt = holder_handle->GetPrototype(); |
- if (pt == Heap::null_value()) return Heap::undefined_value(); |
- result = pt->GetPropertyWithReceiver( |
- *receiver_handle, |
- *name_handle, |
- &attributes); |
- RETURN_IF_SCHEDULED_EXCEPTION(); |
- } |
- break; |
+ return Heap::no_interceptor_result_sentinel(); |
+} |
- case JSObject::kLookupInHolder: |
- result = holder_handle->GetPropertyPostInterceptor( |
- *receiver_handle, |
- *name_handle, |
- &attributes); |
- RETURN_IF_SCHEDULED_EXCEPTION(); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- } |
- |
- if (result->IsFailure()) return result; |
- if (attributes != ABSENT) return result; |
- |
- // 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; |
+} |
+ |
+ |
Object* StoreInterceptorProperty(Arguments args) { |
JSObject* recv = JSObject::cast(args[0]); |
String* name = String::cast(args[1]); |