MIPS: Use LookupIterator for CompileLoadInterceptor and delete Object::Lookup.
authorakos.palfi@imgtec.com <akos.palfi@imgtec.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 18 Aug 2014 19:37:49 +0000 (19:37 +0000)
committerakos.palfi@imgtec.com <akos.palfi@imgtec.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 18 Aug 2014 19:37:49 +0000 (19:37 +0000)
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

src/mips/stub-cache-mips.cc
src/mips64/stub-cache-mips64.cc

index 8f6af7a7fd6c545cb979f726badf48f453820fcd..0dcee22f2a78a4dee81943e31849a8d15bd70bf7 100644 (file)
@@ -794,88 +794,75 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback(
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
-                                                       LookupResult* lookup,
-                                                       Handle<Name> name) {
+void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
+    LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
   DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
 
-  // So far the most popular follow ups for interceptor loads are FIELD
-  // and CALLBACKS, so inline only them, other cases may be added
-  // later.
-  bool compile_followup_inline = false;
-  if (lookup->IsFound() && lookup->IsCacheable()) {
-    if (lookup->IsField()) {
-      compile_followup_inline = true;
-    } else if (lookup->type() == CALLBACKS &&
-        lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
-      Handle<ExecutableAccessorInfo> callback(
-          ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
-      compile_followup_inline =
-          callback->getter() != NULL &&
-          ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
-                                                           type());
+  // Compile the interceptor call, followed by inline code to load the
+  // property from further up the prototype chain if the call fails.
+  // Check that the maps haven't changed.
+  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
+
+  // Preserve the receiver register explicitly whenever it is different from the
+  // holder and it is needed should the interceptor return without any result.
+  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
+  // case might cause a miss during the prototype check.
+  bool must_perform_prototype_check =
+      !holder().is_identical_to(it->GetHolder<JSObject>());
+  bool must_preserve_receiver_reg =
+      !receiver().is(holder_reg) &&
+      (it->property_kind() == LookupIterator::ACCESSOR ||
+       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());
     }
-  }
-
-  if (compile_followup_inline) {
-    // Compile the interceptor call, followed by inline code to load the
-    // property from further up the prototype chain if the call fails.
-    // Check that the maps haven't changed.
-    DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
-
-    // Preserve the receiver register explicitly whenever it is different from
-    // the holder and it is needed should the interceptor return without any
-    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
-    // the FIELD case might cause a miss during the prototype check.
-    bool must_perfrom_prototype_check = *holder() != lookup->holder();
-    bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
-        (lookup->type() == CALLBACKS || must_perfrom_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
-      // 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.
+    // 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);
+    if (must_preserve_receiver_reg) {
+      __ Pop(receiver(), holder_reg, this->name());
+    } else {
+      __ Pop(holder_reg, this->name());
     }
-    GenerateLoadPostInterceptor(holder_reg, name, lookup);
-  } 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);
+    // Leave the internal frame.
   }
+
+  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);
 }
 
 
index fde21a9d121529844bcb4cd8255defb6c9310dfc..4198885f75dace7a80175c9446864aad53436c9c 100644 (file)
@@ -798,88 +798,75 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback(
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg,
-                                                       LookupResult* lookup,
-                                                       Handle<Name> name) {
+void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
+    LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
   DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
 
-  // So far the most popular follow ups for interceptor loads are FIELD
-  // and CALLBACKS, so inline only them, other cases may be added
-  // later.
-  bool compile_followup_inline = false;
-  if (lookup->IsFound() && lookup->IsCacheable()) {
-    if (lookup->IsField()) {
-      compile_followup_inline = true;
-    } else if (lookup->type() == CALLBACKS &&
-        lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
-      Handle<ExecutableAccessorInfo> callback(
-          ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
-      compile_followup_inline =
-          callback->getter() != NULL &&
-          ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback,
-                                                           type());
+  // Compile the interceptor call, followed by inline code to load the
+  // property from further up the prototype chain if the call fails.
+  // Check that the maps haven't changed.
+  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
+
+  // Preserve the receiver register explicitly whenever it is different from the
+  // holder and it is needed should the interceptor return without any result.
+  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
+  // case might cause a miss during the prototype check.
+  bool must_perform_prototype_check =
+      !holder().is_identical_to(it->GetHolder<JSObject>());
+  bool must_preserve_receiver_reg =
+      !receiver().is(holder_reg) &&
+      (it->property_kind() == LookupIterator::ACCESSOR ||
+       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());
     }
-  }
-
-  if (compile_followup_inline) {
-    // Compile the interceptor call, followed by inline code to load the
-    // property from further up the prototype chain if the call fails.
-    // Check that the maps haven't changed.
-    DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
-
-    // Preserve the receiver register explicitly whenever it is different from
-    // the holder and it is needed should the interceptor return without any
-    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
-    // the FIELD case might cause a miss during the prototype check.
-    bool must_perfrom_prototype_check = *holder() != lookup->holder();
-    bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
-        (lookup->type() == CALLBACKS || must_perfrom_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
-      // 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.
+    // 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);
+    if (must_preserve_receiver_reg) {
+      __ Pop(receiver(), holder_reg, this->name());
+    } else {
+      __ Pop(holder_reg, this->name());
     }
-    GenerateLoadPostInterceptor(holder_reg, name, lookup);
-  } 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);
+    // Leave the internal frame.
   }
+
+  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);
 }