Commit 37ce51e0 authored by akos.palfi@imgtec.com's avatar akos.palfi@imgtec.com

MIPS: Use LookupIterator for CompileLoadInterceptor and delete Object::Lookup.

Port r23168 (d860963)

BUG=
R=akos.palfi@imgtec.com

Review URL: https://codereview.chromium.org/473243003

Patch from Balazs Kilvady <balazs.kilvady@imgtec.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23173 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 75ba5e05
...@@ -794,88 +794,75 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( ...@@ -794,88 +794,75 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback(
} }
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(), holder_reg, this->name());
} else {
__ Push(holder_reg, this->name());
} }
} // Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
if (compile_followup_inline) { // of this method).
// Compile the interceptor call, followed by inline code to load the CompileCallLoadPropertyWithInterceptor(
// property from further up the prototype chain if the call fails. masm(), receiver(), holder_reg, this->name(), holder(),
// Check that the maps haven't changed. IC::kLoadPropertyWithInterceptorOnly);
DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
// Check if interceptor provided a value for property. If it's
// Preserve the receiver register explicitly whenever it is different from // the case, return immediately.
// the holder and it is needed should the interceptor return without any Label interceptor_failed;
// result. The CALLBACKS case needs the receiver to be passed into C++ code, __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
// the FIELD case might cause a miss during the prototype check. __ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
bool must_perfrom_prototype_check = *holder() != lookup->holder(); frame_scope.GenerateLeaveFrame();
bool must_preserve_receiver_reg = !receiver().is(holder_reg) && __ Ret();
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
__ bind(&interceptor_failed);
// Save necessary data before invoking an interceptor. if (must_preserve_receiver_reg) {
// Requires a frame to make GC aware of pushed pointers. __ Pop(receiver(), holder_reg, this->name());
{ } else {
FrameScope frame_scope(masm(), StackFrame::INTERNAL); __ Pop(holder_reg, this->name());
if (must_preserve_receiver_reg) {
__ Push(receiver(), holder_reg, this->name());
} else {
__ Push(holder_reg, 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;
__ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
__ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
frame_scope.GenerateLeaveFrame();
__ Ret();
__ bind(&interceptor_failed);
__ pop(this->name());
__ pop(holder_reg);
if (must_preserve_receiver_reg) {
__ pop(receiver());
}
// Leave the internal frame.
} }
GenerateLoadPostInterceptor(holder_reg, name, lookup); // Leave the internal frame.
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
holder());
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
__ TailCallExternalReference(
ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
} }
GenerateLoadPostInterceptor(it, holder_reg);
}
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
// Call the runtime system to load the interceptor.
DCHECK(holder()->HasNamedInterceptor());
DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
holder());
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
__ TailCallExternalReference(
ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
} }
......
...@@ -798,88 +798,75 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( ...@@ -798,88 +798,75 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback(
} }
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(), holder_reg, this->name());
} else {
__ Push(holder_reg, this->name());
} }
} // Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
if (compile_followup_inline) { // of this method).
// Compile the interceptor call, followed by inline code to load the CompileCallLoadPropertyWithInterceptor(
// property from further up the prototype chain if the call fails. masm(), receiver(), holder_reg, this->name(), holder(),
// Check that the maps haven't changed. IC::kLoadPropertyWithInterceptorOnly);
DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
// Check if interceptor provided a value for property. If it's
// Preserve the receiver register explicitly whenever it is different from // the case, return immediately.
// the holder and it is needed should the interceptor return without any Label interceptor_failed;
// result. The CALLBACKS case needs the receiver to be passed into C++ code, __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
// the FIELD case might cause a miss during the prototype check. __ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
bool must_perfrom_prototype_check = *holder() != lookup->holder(); frame_scope.GenerateLeaveFrame();
bool must_preserve_receiver_reg = !receiver().is(holder_reg) && __ Ret();
(lookup->type() == CALLBACKS || must_perfrom_prototype_check);
__ bind(&interceptor_failed);
// Save necessary data before invoking an interceptor. if (must_preserve_receiver_reg) {
// Requires a frame to make GC aware of pushed pointers. __ Pop(receiver(), holder_reg, this->name());
{ } else {
FrameScope frame_scope(masm(), StackFrame::INTERNAL); __ Pop(holder_reg, this->name());
if (must_preserve_receiver_reg) {
__ Push(receiver(), holder_reg, this->name());
} else {
__ Push(holder_reg, 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;
__ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
__ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
frame_scope.GenerateLeaveFrame();
__ Ret();
__ bind(&interceptor_failed);
__ pop(this->name());
__ pop(holder_reg);
if (must_preserve_receiver_reg) {
__ pop(receiver());
}
// Leave the internal frame.
} }
GenerateLoadPostInterceptor(holder_reg, name, lookup); // Leave the internal frame.
} else { // !compile_followup_inline
// Call the runtime system to load the interceptor.
// Check that the maps haven't changed.
PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
holder());
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
__ TailCallExternalReference(
ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
} }
GenerateLoadPostInterceptor(it, holder_reg);
}
void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
// Call the runtime system to load the interceptor.
DCHECK(holder()->HasNamedInterceptor());
DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
holder());
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
__ TailCallExternalReference(
ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment