Get rid of unnecessary handle management when invoking interceptors.
Review URL: http://codereview.chromium.org/155682 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2562 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1ed7462166
commit
4354661a49
@ -505,10 +505,17 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
||||
__ mov(scratch1, Operand(lookup_hint));
|
||||
__ push(scratch1);
|
||||
|
||||
InterceptorInfo* interceptor = holder->GetNamedInterceptor();
|
||||
ASSERT(!Heap::InNewSpace(interceptor));
|
||||
__ mov(scratch1, Operand(Handle<Object>(interceptor)));
|
||||
__ push(scratch1);
|
||||
__ ldr(scratch2, FieldMemOperand(scratch1, InterceptorInfo::kDataOffset));
|
||||
__ push(scratch2);
|
||||
|
||||
// Do tail-call to the runtime system.
|
||||
ExternalReference load_ic_property =
|
||||
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
|
||||
__ TailCallRuntime(load_ic_property, 4);
|
||||
__ TailCallRuntime(load_ic_property, 6);
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,6 +152,27 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
template <typename Pushable>
|
||||
static void PushInterceptorArguments(MacroAssembler* masm,
|
||||
Register receiver,
|
||||
Register holder,
|
||||
Pushable name,
|
||||
JSObject* holder_obj,
|
||||
Smi* lookup_hint) {
|
||||
__ push(receiver);
|
||||
__ push(holder);
|
||||
__ push(name);
|
||||
// TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
|
||||
// LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
|
||||
__ push(Immediate(lookup_hint));
|
||||
|
||||
InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
|
||||
__ mov(receiver, Immediate(Handle<Object>(interceptor)));
|
||||
__ push(receiver);
|
||||
__ push(FieldOperand(receiver, InterceptorInfo::kDataOffset));
|
||||
}
|
||||
|
||||
|
||||
void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
|
||||
int index,
|
||||
Register prototype) {
|
||||
@ -504,18 +525,18 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
||||
|
||||
// Push the arguments on the JS stack of the caller.
|
||||
__ pop(scratch2); // remove return address
|
||||
__ push(receiver); // receiver
|
||||
__ push(reg); // holder
|
||||
__ push(name_reg); // name
|
||||
// TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
|
||||
// LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
|
||||
__ push(Immediate(lookup_hint));
|
||||
PushInterceptorArguments(masm(),
|
||||
receiver,
|
||||
reg,
|
||||
name_reg,
|
||||
holder,
|
||||
lookup_hint);
|
||||
__ push(scratch2); // restore return address
|
||||
|
||||
// Do tail-call to the runtime system.
|
||||
ExternalReference load_ic_property =
|
||||
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
|
||||
__ TailCallRuntime(load_ic_property, 4);
|
||||
__ TailCallRuntime(load_ic_property, 6);
|
||||
}
|
||||
|
||||
|
||||
@ -744,15 +765,17 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
|
||||
__ EnterInternalFrame();
|
||||
|
||||
// Push arguments on the expression stack.
|
||||
__ push(edx); // receiver
|
||||
__ push(reg); // holder
|
||||
__ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
|
||||
__ push(Immediate(holder->InterceptorPropertyLookupHint(name)));
|
||||
PushInterceptorArguments(masm(),
|
||||
edx,
|
||||
reg,
|
||||
Operand(ebp, (argc + 3) * kPointerSize),
|
||||
holder,
|
||||
holder->InterceptorPropertyLookupHint(name));
|
||||
|
||||
// Perform call.
|
||||
ExternalReference load_interceptor =
|
||||
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
|
||||
__ mov(eax, Immediate(4));
|
||||
__ mov(eax, Immediate(6));
|
||||
__ mov(ebx, Immediate(load_interceptor));
|
||||
|
||||
CEntryStub stub;
|
||||
|
@ -6028,12 +6028,12 @@ Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver,
|
||||
}
|
||||
|
||||
|
||||
Object* JSObject::GetPropertyWithInterceptorProper(
|
||||
Object* JSObject::GetPropertyWithInterceptor(
|
||||
JSObject* receiver,
|
||||
String* name,
|
||||
PropertyAttributes* attributes) {
|
||||
InterceptorInfo* interceptor = GetNamedInterceptor();
|
||||
HandleScope scope;
|
||||
Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
|
||||
Handle<JSObject> receiver_handle(receiver);
|
||||
Handle<JSObject> holder_handle(this);
|
||||
Handle<String> name_handle(name);
|
||||
@ -6052,85 +6052,14 @@ Object* JSObject::GetPropertyWithInterceptorProper(
|
||||
VMState state(EXTERNAL);
|
||||
result = getter(v8::Utils::ToLocal(name_handle), info);
|
||||
}
|
||||
if (!Top::has_scheduled_exception() && !result.IsEmpty()) {
|
||||
RETURN_IF_SCHEDULED_EXCEPTION();
|
||||
if (!result.IsEmpty()) {
|
||||
*attributes = NONE;
|
||||
return *v8::Utils::OpenHandle(*result);
|
||||
}
|
||||
}
|
||||
|
||||
*attributes = ABSENT;
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
|
||||
Object* JSObject::GetInterceptorPropertyWithLookupHint(
|
||||
JSObject* receiver,
|
||||
Smi* lookup_hint,
|
||||
String* name,
|
||||
PropertyAttributes* attributes) {
|
||||
HandleScope scope;
|
||||
Handle<JSObject> receiver_handle(receiver);
|
||||
Handle<JSObject> holder_handle(this);
|
||||
Handle<String> name_handle(name);
|
||||
|
||||
Object* result = GetPropertyWithInterceptorProper(receiver,
|
||||
name,
|
||||
attributes);
|
||||
if (*attributes != ABSENT) {
|
||||
return result;
|
||||
}
|
||||
RETURN_IF_SCHEDULED_EXCEPTION();
|
||||
|
||||
int property_index = lookup_hint->value();
|
||||
if (property_index >= 0) {
|
||||
result = holder_handle->FastPropertyAt(property_index);
|
||||
} else {
|
||||
switch (property_index) {
|
||||
case kLookupInPrototype: {
|
||||
Object* pt = holder_handle->GetPrototype();
|
||||
*attributes = ABSENT;
|
||||
if (pt == Heap::null_value()) return Heap::undefined_value();
|
||||
result = pt->GetPropertyWithReceiver(
|
||||
*receiver_handle,
|
||||
*name_handle,
|
||||
attributes);
|
||||
RETURN_IF_SCHEDULED_EXCEPTION();
|
||||
}
|
||||
break;
|
||||
|
||||
case kLookupInHolder:
|
||||
result = holder_handle->GetPropertyPostInterceptor(
|
||||
*receiver_handle,
|
||||
*name_handle,
|
||||
attributes);
|
||||
RETURN_IF_SCHEDULED_EXCEPTION();
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Object* JSObject::GetPropertyWithInterceptor(
|
||||
JSObject* receiver,
|
||||
String* name,
|
||||
PropertyAttributes* attributes) {
|
||||
HandleScope scope;
|
||||
Handle<JSObject> receiver_handle(receiver);
|
||||
Handle<JSObject> holder_handle(this);
|
||||
Handle<String> name_handle(name);
|
||||
|
||||
Object* result = GetPropertyWithInterceptorProper(receiver, name, attributes);
|
||||
if (*attributes != ABSENT) {
|
||||
return result;
|
||||
}
|
||||
RETURN_IF_SCHEDULED_EXCEPTION();
|
||||
|
||||
result = holder_handle->GetPropertyPostInterceptor(
|
||||
Object* result = holder_handle->GetPropertyPostInterceptor(
|
||||
*receiver_handle,
|
||||
*name_handle,
|
||||
attributes);
|
||||
|
@ -1508,10 +1508,6 @@ class JSObject: public HeapObject {
|
||||
void LookupCallback(String* name, LookupResult* result);
|
||||
|
||||
inline Smi* InterceptorPropertyLookupHint(String* name);
|
||||
Object* GetInterceptorPropertyWithLookupHint(JSObject* receiver,
|
||||
Smi* lookup_hint,
|
||||
String* name,
|
||||
PropertyAttributes* attributes);
|
||||
static const int kLookupInHolder = -1;
|
||||
static const int kLookupInPrototype = -2;
|
||||
|
||||
@ -1706,12 +1702,6 @@ class JSObject: public HeapObject {
|
||||
|
||||
void LookupInDescriptor(String* name, LookupResult* result);
|
||||
|
||||
// Attempts to get property with a named interceptor getter.
|
||||
// Sets |attributes| to ABSENT if interceptor didn't return anything
|
||||
Object* GetPropertyWithInterceptorProper(JSObject* receiver,
|
||||
String* name,
|
||||
PropertyAttributes* attributes);
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
|
||||
};
|
||||
|
||||
|
@ -789,19 +789,70 @@ Object* StoreCallbackProperty(Arguments args) {
|
||||
|
||||
|
||||
Object* LoadInterceptorProperty(Arguments args) {
|
||||
JSObject* recv = JSObject::cast(args[0]);
|
||||
JSObject* holder = JSObject::cast(args[1]);
|
||||
String* name = String::cast(args[2]);
|
||||
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]);
|
||||
ASSERT(holder->HasNamedInterceptor());
|
||||
PropertyAttributes attr = NONE;
|
||||
Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(4);
|
||||
Handle<Object> data_handle = args.at<Object>(5);
|
||||
|
||||
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),
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
case JSObject::kLookupInHolder:
|
||||
result = holder_handle->GetPropertyPostInterceptor(
|
||||
*receiver_handle,
|
||||
*name_handle,
|
||||
&attributes);
|
||||
RETURN_IF_SCHEDULED_EXCEPTION();
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
Object* result = holder->GetInterceptorPropertyWithLookupHint(
|
||||
recv, lookup_hint, name, &attr);
|
||||
if (result->IsFailure()) return result;
|
||||
|
||||
// If the property is present, return it.
|
||||
if (attr != ABSENT) 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
|
||||
|
Loading…
Reference in New Issue
Block a user