Comment the code for loading and calling with interceptor.
Review URL: http://codereview.chromium.org/2124021 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4717 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
22e4847fde
commit
f6ec1b4f26
@ -436,7 +436,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
Register holder,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
LookupResult* lookup,
|
||||
String* name,
|
||||
Label* miss_label) {
|
||||
@ -456,7 +456,8 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
}
|
||||
|
||||
if (!optimize) {
|
||||
CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
|
||||
CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
|
||||
miss_label);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -466,14 +467,18 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ push(receiver);
|
||||
__ Push(holder, name_);
|
||||
|
||||
// Invoke an interceptor. Note: map checks from receiver to
|
||||
// interceptor's holder has been compiled before (see a caller
|
||||
// of this method.)
|
||||
CompileCallLoadPropertyWithInterceptor(masm,
|
||||
receiver,
|
||||
holder,
|
||||
name_,
|
||||
holder_obj);
|
||||
interceptor_holder);
|
||||
|
||||
// Check if interceptor provided a value for property. If it's
|
||||
// the case, return immediately.
|
||||
Label interceptor_failed;
|
||||
// Compare with no_interceptor_result_sentinel.
|
||||
__ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
|
||||
__ cmp(r0, scratch1);
|
||||
__ b(eq, &interceptor_failed);
|
||||
@ -488,13 +493,17 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
if (lookup->type() == FIELD) {
|
||||
holder = stub_compiler->CheckPrototypes(holder_obj,
|
||||
// We found FIELD property in prototype chain of interceptor's holder.
|
||||
// Check that the maps from interceptor's holder to field's holder
|
||||
// haven't changed...
|
||||
holder = stub_compiler->CheckPrototypes(interceptor_holder,
|
||||
holder,
|
||||
lookup->holder(),
|
||||
scratch1,
|
||||
scratch2,
|
||||
name,
|
||||
miss_label);
|
||||
// ... and retrieve a field from field's holder.
|
||||
stub_compiler->GenerateFastPropertyLoad(masm,
|
||||
r0,
|
||||
holder,
|
||||
@ -502,30 +511,38 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
lookup->GetFieldIndex());
|
||||
__ Ret();
|
||||
} else {
|
||||
// We found CALLBACKS property in prototype chain of interceptor's
|
||||
// holder.
|
||||
ASSERT(lookup->type() == CALLBACKS);
|
||||
ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
|
||||
ASSERT(callback != NULL);
|
||||
ASSERT(callback->getter() != NULL);
|
||||
|
||||
// Prepare for tail call: push receiver to stack.
|
||||
Label cleanup;
|
||||
__ push(receiver);
|
||||
|
||||
holder = stub_compiler->CheckPrototypes(holder_obj, holder,
|
||||
// Check that the maps from interceptor's holder to callback's holder
|
||||
// haven't changed.
|
||||
holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
|
||||
lookup->holder(), scratch1,
|
||||
scratch2,
|
||||
name,
|
||||
&cleanup);
|
||||
|
||||
// Continue tail call preparation: push remaining parameters.
|
||||
__ push(holder);
|
||||
__ Move(holder, Handle<AccessorInfo>(callback));
|
||||
__ push(holder);
|
||||
__ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset));
|
||||
__ Push(scratch1, name_);
|
||||
|
||||
// Tail call to runtime.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
|
||||
__ TailCallExternalReference(ref, 5, 1);
|
||||
|
||||
// Clean up code: we pushed receiver and need to remove it.
|
||||
__ bind(&cleanup);
|
||||
__ pop(scratch2);
|
||||
}
|
||||
@ -536,9 +553,9 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
Register receiver,
|
||||
Register holder,
|
||||
Register scratch,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
Label* miss_label) {
|
||||
PushInterceptorArguments(masm, receiver, holder, name_, holder_obj);
|
||||
PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
|
||||
|
||||
ExternalReference ref = ExternalReference(
|
||||
IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
|
||||
@ -714,7 +731,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
Register receiver,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
LookupResult* lookup,
|
||||
String* name,
|
||||
const CallOptimization& optimization,
|
||||
@ -727,10 +744,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
bool can_do_fast_api_call = false;
|
||||
if (optimization.is_simple_api_call() &&
|
||||
!lookup->holder()->IsGlobalObject()) {
|
||||
depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj);
|
||||
depth1 =
|
||||
optimization.GetPrototypeDepthOfExpectedType(object,
|
||||
interceptor_holder);
|
||||
if (depth1 == kInvalidProtoDepth) {
|
||||
depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj,
|
||||
lookup->holder());
|
||||
depth2 =
|
||||
optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
|
||||
lookup->holder());
|
||||
}
|
||||
can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
|
||||
(depth2 != kInvalidProtoDepth);
|
||||
@ -745,23 +765,31 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
ReserveSpaceForFastApiCall(masm, scratch1);
|
||||
}
|
||||
|
||||
// Check that the maps from receiver to interceptor's holder
|
||||
// haven't changed and thus we can invoke interceptor.
|
||||
Label miss_cleanup;
|
||||
Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
|
||||
Register holder =
|
||||
stub_compiler_->CheckPrototypes(object, receiver, holder_obj, scratch1,
|
||||
scratch2, name, depth1, miss);
|
||||
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
||||
scratch1, scratch2, name,
|
||||
depth1, miss);
|
||||
|
||||
// Invoke an interceptor and if it provides a value,
|
||||
// branch to |regular_invoke|.
|
||||
Label regular_invoke;
|
||||
LoadWithInterceptor(masm, receiver, holder, holder_obj, scratch2,
|
||||
LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
|
||||
®ular_invoke);
|
||||
|
||||
// Generate code for the failed interceptor case.
|
||||
// Interceptor returned nothing for this property. Try to use cached
|
||||
// constant function.
|
||||
|
||||
// Check the lookup is still valid.
|
||||
stub_compiler_->CheckPrototypes(holder_obj, receiver,
|
||||
// Check that the maps from interceptor's holder to constant function's
|
||||
// holder haven't changed and thus we can use cached constant function.
|
||||
stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
|
||||
lookup->holder(), scratch1,
|
||||
scratch2, name, depth2, miss);
|
||||
|
||||
// Invoke function.
|
||||
if (can_do_fast_api_call) {
|
||||
GenerateFastApiCall(masm, optimization, arguments_.immediate());
|
||||
} else {
|
||||
@ -769,12 +797,14 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
JUMP_FUNCTION);
|
||||
}
|
||||
|
||||
// Deferred code for fast API call case---clean preallocated space.
|
||||
if (can_do_fast_api_call) {
|
||||
__ bind(&miss_cleanup);
|
||||
FreeSpaceForFastApiCall(masm);
|
||||
__ b(miss_label);
|
||||
}
|
||||
|
||||
// Invoke a regular function.
|
||||
__ bind(®ular_invoke);
|
||||
if (can_do_fast_api_call) {
|
||||
FreeSpaceForFastApiCall(masm);
|
||||
@ -787,10 +817,10 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
String* name,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
Label* miss_label) {
|
||||
Register holder =
|
||||
stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
|
||||
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
||||
scratch1, scratch2, name,
|
||||
miss_label);
|
||||
|
||||
@ -803,7 +833,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
receiver,
|
||||
holder,
|
||||
name_,
|
||||
holder_obj);
|
||||
interceptor_holder);
|
||||
|
||||
__ CallExternalReference(
|
||||
ExternalReference(
|
||||
|
@ -356,7 +356,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
Register holder,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
LookupResult* lookup,
|
||||
String* name,
|
||||
Label* miss_label) {
|
||||
@ -376,7 +376,8 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
}
|
||||
|
||||
if (!optimize) {
|
||||
CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
|
||||
CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
|
||||
miss_label);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -389,12 +390,17 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ push(holder);
|
||||
__ push(name_);
|
||||
|
||||
// Invoke an interceptor. Note: map checks from receiver to
|
||||
// interceptor's holder has been compiled before (see a caller
|
||||
// of this method.)
|
||||
CompileCallLoadPropertyWithInterceptor(masm,
|
||||
receiver,
|
||||
holder,
|
||||
name_,
|
||||
holder_obj);
|
||||
interceptor_holder);
|
||||
|
||||
// Check if interceptor provided a value for property. If it's
|
||||
// the case, return immediately.
|
||||
Label interceptor_failed;
|
||||
__ cmp(eax, Factory::no_interceptor_result_sentinel());
|
||||
__ j(equal, &interceptor_failed);
|
||||
@ -411,47 +417,61 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
if (lookup->type() == FIELD) {
|
||||
holder = stub_compiler->CheckPrototypes(holder_obj, holder,
|
||||
// We found FIELD property in prototype chain of interceptor's holder.
|
||||
// Check that the maps from interceptor's holder to field's holder
|
||||
// haven't changed...
|
||||
holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
|
||||
lookup->holder(), scratch1,
|
||||
scratch2,
|
||||
name,
|
||||
miss_label);
|
||||
// ... and retrieve a field from field's holder.
|
||||
stub_compiler->GenerateFastPropertyLoad(masm, eax,
|
||||
holder, lookup->holder(),
|
||||
lookup->GetFieldIndex());
|
||||
__ ret(0);
|
||||
} else {
|
||||
// We found CALLBACKS property in prototype chain of interceptor's
|
||||
// holder.
|
||||
ASSERT(lookup->type() == CALLBACKS);
|
||||
ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
|
||||
ASSERT(callback != NULL);
|
||||
ASSERT(callback->getter() != NULL);
|
||||
|
||||
// Prepare for tail call: push receiver to stack after return address.
|
||||
Label cleanup;
|
||||
__ pop(scratch2);
|
||||
__ pop(scratch2); // return address
|
||||
__ push(receiver);
|
||||
__ push(scratch2);
|
||||
|
||||
holder = stub_compiler->CheckPrototypes(holder_obj, holder,
|
||||
// Check that the maps from interceptor's holder to callback's holder
|
||||
// haven't changed.
|
||||
holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
|
||||
lookup->holder(), scratch1,
|
||||
scratch2,
|
||||
name,
|
||||
&cleanup);
|
||||
|
||||
__ pop(scratch2); // save old return address
|
||||
// Continue tail call preparation: push remaining parameters after
|
||||
// return address.
|
||||
__ pop(scratch2); // return address
|
||||
__ push(holder);
|
||||
__ mov(holder, Immediate(Handle<AccessorInfo>(callback)));
|
||||
__ push(holder);
|
||||
__ push(FieldOperand(holder, AccessorInfo::kDataOffset));
|
||||
__ push(name_);
|
||||
__ push(scratch2); // restore old return address
|
||||
__ push(scratch2); // restore return address
|
||||
|
||||
// Tail call to runtime.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
|
||||
__ TailCallExternalReference(ref, 5, 1);
|
||||
|
||||
// Clean up code: we pushed receiver after return address and
|
||||
// need to remove it from there.
|
||||
__ bind(&cleanup);
|
||||
__ pop(scratch1);
|
||||
__ pop(scratch2);
|
||||
__ pop(scratch1); // return address.
|
||||
__ pop(scratch2); // receiver.
|
||||
__ push(scratch1);
|
||||
}
|
||||
}
|
||||
@ -461,10 +481,10 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
Register receiver,
|
||||
Register holder,
|
||||
Register scratch,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
Label* miss_label) {
|
||||
__ pop(scratch); // save old return address
|
||||
PushInterceptorArguments(masm, receiver, holder, name_, holder_obj);
|
||||
PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
|
||||
__ push(scratch); // restore old return address
|
||||
|
||||
ExternalReference ref = ExternalReference(
|
||||
@ -626,7 +646,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
Register receiver,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
LookupResult* lookup,
|
||||
String* name,
|
||||
const CallOptimization& optimization,
|
||||
@ -639,10 +659,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
bool can_do_fast_api_call = false;
|
||||
if (optimization.is_simple_api_call() &&
|
||||
!lookup->holder()->IsGlobalObject()) {
|
||||
depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj);
|
||||
depth1 =
|
||||
optimization.GetPrototypeDepthOfExpectedType(object,
|
||||
interceptor_holder);
|
||||
if (depth1 == kInvalidProtoDepth) {
|
||||
depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj,
|
||||
lookup->holder());
|
||||
depth2 =
|
||||
optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
|
||||
lookup->holder());
|
||||
}
|
||||
can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
|
||||
(depth2 != kInvalidProtoDepth);
|
||||
@ -655,24 +678,32 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
ReserveSpaceForFastApiCall(masm, scratch1);
|
||||
}
|
||||
|
||||
// Check that the maps from receiver to interceptor's holder
|
||||
// haven't changed and thus we can invoke interceptor.
|
||||
Label miss_cleanup;
|
||||
Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
|
||||
Register holder =
|
||||
stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
|
||||
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
||||
scratch1, scratch2, name,
|
||||
depth1, miss);
|
||||
|
||||
// Invoke an interceptor and if it provides a value,
|
||||
// branch to |regular_invoke|.
|
||||
Label regular_invoke;
|
||||
LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke);
|
||||
LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
|
||||
®ular_invoke);
|
||||
|
||||
// Generate code for the failed interceptor case.
|
||||
// Interceptor returned nothing for this property. Try to use cached
|
||||
// constant function.
|
||||
|
||||
// Check the lookup is still valid.
|
||||
stub_compiler_->CheckPrototypes(holder_obj, receiver,
|
||||
// Check that the maps from interceptor's holder to constant function's
|
||||
// holder haven't changed and thus we can use cached constant function.
|
||||
stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
|
||||
lookup->holder(),
|
||||
scratch1, scratch2, name,
|
||||
depth2, miss);
|
||||
|
||||
// Invoke function.
|
||||
if (can_do_fast_api_call) {
|
||||
GenerateFastApiCall(masm, optimization, arguments_.immediate());
|
||||
} else {
|
||||
@ -680,12 +711,14 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
JUMP_FUNCTION);
|
||||
}
|
||||
|
||||
// Deferred code for fast API call case---clean preallocated space.
|
||||
if (can_do_fast_api_call) {
|
||||
__ bind(&miss_cleanup);
|
||||
FreeSpaceForFastApiCall(masm, scratch1);
|
||||
__ jmp(miss_label);
|
||||
}
|
||||
|
||||
// Invoke a regular function.
|
||||
__ bind(®ular_invoke);
|
||||
if (can_do_fast_api_call) {
|
||||
FreeSpaceForFastApiCall(masm, scratch1);
|
||||
@ -698,10 +731,10 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
String* name,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
Label* miss_label) {
|
||||
Register holder =
|
||||
stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
|
||||
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
||||
scratch1, scratch2, name,
|
||||
miss_label);
|
||||
|
||||
@ -713,7 +746,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
receiver,
|
||||
holder,
|
||||
name_,
|
||||
holder_obj);
|
||||
interceptor_holder);
|
||||
|
||||
__ CallExternalReference(
|
||||
ExternalReference(
|
||||
|
@ -430,7 +430,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
Register holder,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
LookupResult* lookup,
|
||||
String* name,
|
||||
Label* miss_label) {
|
||||
@ -450,7 +450,8 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
}
|
||||
|
||||
if (!optimize) {
|
||||
CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
|
||||
CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
|
||||
miss_label);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -463,12 +464,17 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ push(holder);
|
||||
__ push(name_);
|
||||
|
||||
// Invoke an interceptor. Note: map checks from receiver to
|
||||
// interceptor's holder has been compiled before (see a caller
|
||||
// of this method.)
|
||||
CompileCallLoadPropertyWithInterceptor(masm,
|
||||
receiver,
|
||||
holder,
|
||||
name_,
|
||||
holder_obj);
|
||||
interceptor_holder);
|
||||
|
||||
// Check if interceptor provided a value for property. If it's
|
||||
// the case, return immediately.
|
||||
Label interceptor_failed;
|
||||
__ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
|
||||
__ j(equal, &interceptor_failed);
|
||||
@ -485,13 +491,17 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
if (lookup->type() == FIELD) {
|
||||
holder = stub_compiler->CheckPrototypes(holder_obj,
|
||||
// We found FIELD property in prototype chain of interceptor's holder.
|
||||
// Check that the maps from interceptor's holder to field's holder
|
||||
// haven't changed...
|
||||
holder = stub_compiler->CheckPrototypes(interceptor_holder,
|
||||
holder,
|
||||
lookup->holder(),
|
||||
scratch1,
|
||||
scratch2,
|
||||
name,
|
||||
miss_label);
|
||||
// ... and retrieve a field from field's holder.
|
||||
stub_compiler->GenerateFastPropertyLoad(masm,
|
||||
rax,
|
||||
holder,
|
||||
@ -499,37 +509,47 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
lookup->GetFieldIndex());
|
||||
__ ret(0);
|
||||
} else {
|
||||
// We found CALLBACKS property in prototype chain of interceptor's
|
||||
// holder.
|
||||
ASSERT(lookup->type() == CALLBACKS);
|
||||
ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
|
||||
ASSERT(callback != NULL);
|
||||
ASSERT(callback->getter() != NULL);
|
||||
|
||||
// Prepare for tail call. Push receiver to stack after return address.
|
||||
Label cleanup;
|
||||
__ pop(scratch2);
|
||||
__ pop(scratch2); // return address
|
||||
__ push(receiver);
|
||||
__ push(scratch2);
|
||||
|
||||
holder = stub_compiler->CheckPrototypes(holder_obj, holder,
|
||||
// Check that the maps from interceptor's holder to callback's holder
|
||||
// haven't changed.
|
||||
holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
|
||||
lookup->holder(), scratch1,
|
||||
scratch2,
|
||||
name,
|
||||
&cleanup);
|
||||
|
||||
__ pop(scratch2); // save old return address
|
||||
// Continue tail call preparation: push remaining parameters after
|
||||
// return address.
|
||||
__ pop(scratch2); // return address
|
||||
__ push(holder);
|
||||
__ Move(holder, Handle<AccessorInfo>(callback));
|
||||
__ push(holder);
|
||||
__ push(FieldOperand(holder, AccessorInfo::kDataOffset));
|
||||
__ push(name_);
|
||||
__ push(scratch2); // restore old return address
|
||||
__ push(scratch2); // restore return address
|
||||
|
||||
// Tail call to runtime.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
|
||||
__ TailCallExternalReference(ref, 5, 1);
|
||||
|
||||
// Clean up code: we pushed receiver after return address and
|
||||
// need to remove it from there.
|
||||
__ bind(&cleanup);
|
||||
__ pop(scratch1);
|
||||
__ pop(scratch2);
|
||||
__ pop(scratch1); // return address
|
||||
__ pop(scratch2); // receiver
|
||||
__ push(scratch1);
|
||||
}
|
||||
}
|
||||
@ -539,10 +559,10 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
Register receiver,
|
||||
Register holder,
|
||||
Register scratch,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
Label* miss_label) {
|
||||
__ pop(scratch); // save old return address
|
||||
PushInterceptorArguments(masm, receiver, holder, name_, holder_obj);
|
||||
PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
|
||||
__ push(scratch); // restore old return address
|
||||
|
||||
ExternalReference ref = ExternalReference(
|
||||
@ -704,7 +724,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
Register receiver,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
LookupResult* lookup,
|
||||
String* name,
|
||||
const CallOptimization& optimization,
|
||||
@ -717,10 +737,13 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
bool can_do_fast_api_call = false;
|
||||
if (optimization.is_simple_api_call() &&
|
||||
!lookup->holder()->IsGlobalObject()) {
|
||||
depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj);
|
||||
depth1 =
|
||||
optimization.GetPrototypeDepthOfExpectedType(object,
|
||||
interceptor_holder);
|
||||
if (depth1 == kInvalidProtoDepth) {
|
||||
depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj,
|
||||
lookup->holder());
|
||||
depth2 =
|
||||
optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
|
||||
lookup->holder());
|
||||
}
|
||||
can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
|
||||
(depth2 != kInvalidProtoDepth);
|
||||
@ -733,24 +756,32 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
ReserveSpaceForFastApiCall(masm, scratch1);
|
||||
}
|
||||
|
||||
// Check that the maps from receiver to interceptor's holder
|
||||
// haven't changed and thus we can invoke interceptor.
|
||||
Label miss_cleanup;
|
||||
Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
|
||||
Register holder =
|
||||
stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
|
||||
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
||||
scratch1, scratch2, name,
|
||||
depth1, miss);
|
||||
|
||||
// Invoke an interceptor and if it provides a value,
|
||||
// branch to |regular_invoke|.
|
||||
Label regular_invoke;
|
||||
LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke);
|
||||
LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
|
||||
®ular_invoke);
|
||||
|
||||
// Generate code for the failed interceptor case.
|
||||
// Interceptor returned nothing for this property. Try to use cached
|
||||
// constant function.
|
||||
|
||||
// Check the lookup is still valid.
|
||||
stub_compiler_->CheckPrototypes(holder_obj, receiver,
|
||||
// Check that the maps from interceptor's holder to constant function's
|
||||
// holder haven't changed and thus we can use cached constant function.
|
||||
stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
|
||||
lookup->holder(),
|
||||
scratch1, scratch2, name,
|
||||
depth2, miss);
|
||||
|
||||
// Invoke function.
|
||||
if (can_do_fast_api_call) {
|
||||
GenerateFastApiCall(masm, optimization, arguments_.immediate());
|
||||
} else {
|
||||
@ -758,12 +789,14 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
JUMP_FUNCTION);
|
||||
}
|
||||
|
||||
// Deferred code for fast API call case---clean preallocated space.
|
||||
if (can_do_fast_api_call) {
|
||||
__ bind(&miss_cleanup);
|
||||
FreeSpaceForFastApiCall(masm, scratch1);
|
||||
__ jmp(miss_label);
|
||||
}
|
||||
|
||||
// Invoke a regular function.
|
||||
__ bind(®ular_invoke);
|
||||
if (can_do_fast_api_call) {
|
||||
FreeSpaceForFastApiCall(masm, scratch1);
|
||||
@ -776,10 +809,10 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
String* name,
|
||||
JSObject* holder_obj,
|
||||
JSObject* interceptor_holder,
|
||||
Label* miss_label) {
|
||||
Register holder =
|
||||
stub_compiler_->CheckPrototypes(object, receiver, holder_obj,
|
||||
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
||||
scratch1, scratch2, name,
|
||||
miss_label);
|
||||
|
||||
@ -791,7 +824,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
receiver,
|
||||
holder,
|
||||
name_,
|
||||
holder_obj);
|
||||
interceptor_holder);
|
||||
|
||||
__ CallExternalReference(
|
||||
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
|
||||
|
Loading…
Reference in New Issue
Block a user