X87: Use LookupIterator for CompileLoadInterceptor and delete Object::Lookup
port r23168. original commit message: Use LookupIterator for CompileLoadInterceptor and delete Object::Lookup BUG= R=weiliang.lin@intel.com Review URL: https://codereview.chromium.org/481323002 Patch from Chunyang Dai <chunyang.dai@intel.com>. git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23176 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
936d7218b4
commit
3170fbb305
@ -778,102 +778,87 @@ void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupResult* lookup,
|
LookupIterator* it, Register holder_reg) {
|
||||||
Handle<Name> name) {
|
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
|
DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
|
||||||
|
|
||||||
// So far the most popular follow ups for interceptor loads are FIELD
|
// Compile the interceptor call, followed by inline code to load the
|
||||||
// and CALLBACKS, so inline only them, other cases may be added
|
// property from further up the prototype chain if the call fails.
|
||||||
// later.
|
// Check that the maps haven't changed.
|
||||||
bool compile_followup_inline = false;
|
DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
|
||||||
if (lookup->IsFound() && lookup->IsCacheable()) {
|
|
||||||
if (lookup->IsField()) {
|
// Preserve the receiver register explicitly whenever it is different from the
|
||||||
compile_followup_inline = true;
|
// holder and it is needed should the interceptor return without any result.
|
||||||
} else if (lookup->type() == CALLBACKS &&
|
// The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
|
||||||
lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
|
// case might cause a miss during the prototype check.
|
||||||
Handle<ExecutableAccessorInfo> callback(
|
bool must_perform_prototype_check =
|
||||||
ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
|
!holder().is_identical_to(it->GetHolder<JSObject>());
|
||||||
compile_followup_inline =
|
bool must_preserve_receiver_reg =
|
||||||
callback->getter() != NULL &&
|
!receiver().is(holder_reg) &&
|
||||||
ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
|
(it->property_kind() == LookupIterator::ACCESSOR ||
|
||||||
type());
|
must_perform_prototype_check);
|
||||||
|
|
||||||
|
// Save necessary data before invoking an interceptor.
|
||||||
|
// Requires a frame to make GC aware of pushed pointers.
|
||||||
|
{
|
||||||
|
FrameScope frame_scope(masm(), StackFrame::INTERNAL);
|
||||||
|
|
||||||
|
if (must_preserve_receiver_reg) {
|
||||||
|
__ push(receiver());
|
||||||
}
|
}
|
||||||
}
|
__ push(holder_reg);
|
||||||
|
__ push(this->name());
|
||||||
|
|
||||||
if (compile_followup_inline) {
|
// Invoke an interceptor. Note: map checks from receiver to
|
||||||
// Compile the interceptor call, followed by inline code to load the
|
// interceptor's holder has been compiled before (see a caller
|
||||||
// property from further up the prototype chain if the call fails.
|
// of this method.)
|
||||||
// Check that the maps haven't changed.
|
CompileCallLoadPropertyWithInterceptor(
|
||||||
DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
|
masm(), receiver(), holder_reg, this->name(), holder(),
|
||||||
|
IC::kLoadPropertyWithInterceptorOnly);
|
||||||
|
|
||||||
// Preserve the receiver register explicitly whenever it is different from
|
// Check if interceptor provided a value for property. If it's
|
||||||
// the holder and it is needed should the interceptor return without any
|
// the case, return immediately.
|
||||||
// result. The CALLBACKS case needs the receiver to be passed into C++ code,
|
Label interceptor_failed;
|
||||||
// the FIELD case might cause a miss during the prototype check.
|
__ cmp(eax, factory()->no_interceptor_result_sentinel());
|
||||||
bool must_perfrom_prototype_check = *holder() != lookup->holder();
|
__ j(equal, &interceptor_failed);
|
||||||
bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
|
frame_scope.GenerateLeaveFrame();
|
||||||
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
|
__ ret(0);
|
||||||
|
|
||||||
// Save necessary data before invoking an interceptor.
|
// Clobber registers when generating debug-code to provoke errors.
|
||||||
// Requires a frame to make GC aware of pushed pointers.
|
__ bind(&interceptor_failed);
|
||||||
{
|
if (FLAG_debug_code) {
|
||||||
FrameScope frame_scope(masm(), StackFrame::INTERNAL);
|
__ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue)));
|
||||||
|
__ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
|
||||||
if (must_preserve_receiver_reg) {
|
__ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue)));
|
||||||
__ push(receiver());
|
|
||||||
}
|
|
||||||
__ push(holder_reg);
|
|
||||||
__ push(this->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_reg, this->name(), holder(),
|
|
||||||
IC::kLoadPropertyWithInterceptorOnly);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
frame_scope.GenerateLeaveFrame();
|
|
||||||
__ ret(0);
|
|
||||||
|
|
||||||
// Clobber registers when generating debug-code to provoke errors.
|
|
||||||
__ bind(&interceptor_failed);
|
|
||||||
if (FLAG_debug_code) {
|
|
||||||
__ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue)));
|
|
||||||
__ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
|
|
||||||
__ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue)));
|
|
||||||
}
|
|
||||||
|
|
||||||
__ pop(this->name());
|
|
||||||
__ pop(holder_reg);
|
|
||||||
if (must_preserve_receiver_reg) {
|
|
||||||
__ pop(receiver());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leave the internal frame.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateLoadPostInterceptor(holder_reg, name, lookup);
|
__ pop(this->name());
|
||||||
} else { // !compile_followup_inline
|
__ pop(holder_reg);
|
||||||
// Call the runtime system to load the interceptor.
|
if (must_preserve_receiver_reg) {
|
||||||
// Check that the maps haven't changed.
|
__ pop(receiver());
|
||||||
__ pop(scratch2()); // save old return address
|
}
|
||||||
PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
|
|
||||||
holder());
|
|
||||||
__ push(scratch2()); // restore old return address
|
|
||||||
|
|
||||||
ExternalReference ref =
|
// Leave the internal frame.
|
||||||
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor),
|
|
||||||
isolate());
|
|
||||||
__ TailCallExternalReference(
|
|
||||||
ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenerateLoadPostInterceptor(it, holder_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
|
||||||
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
|
||||||
|
// Call the runtime system to load the interceptor.
|
||||||
|
__ pop(scratch2()); // save old return address
|
||||||
|
PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
|
||||||
|
holder());
|
||||||
|
__ push(scratch2()); // restore old return address
|
||||||
|
|
||||||
|
ExternalReference ref = ExternalReference(
|
||||||
|
IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
|
||||||
|
__ TailCallExternalReference(
|
||||||
|
ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user