MIPS: To aid vector-based load ic work, we need to be able to handle the megamorphic...
authorbalazs.kilvady@imgtec.com <balazs.kilvady@imgtec.com>
Mon, 8 Sep 2014 17:20:49 +0000 (17:20 +0000)
committerbalazs.kilvady@imgtec.com <balazs.kilvady@imgtec.com>
Mon, 8 Sep 2014 17:20:49 +0000 (17:20 +0000)
Port r23772 (d6d07c5)

Original commit message:
Encapsulate megamorphic load/tail-call in hydrogen.

A simple approach is to wrap the probe activity in a hydrogen instruction.

The instruction is novel in that it always tail-calls away.

BUG=
R=paul.lind@imgtec.com

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ic/mips/ic-mips.cc
src/ic/mips/stub-cache-mips.cc
src/ic/mips64/ic-mips64.cc
src/ic/mips64/stub-cache-mips64.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/mips64/lithium-codegen-mips64.cc
src/mips64/lithium-mips64.cc
src/mips64/lithium-mips64.h

index 3b7f00362c60fe411c957da60e145c22f582ddae..dfbfff07e4e37690c59b15537799a15967e1ace8 100644 (file)
@@ -249,24 +249,6 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
 }
 
 
-void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // The return address is in lr.
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register name = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(a1));
-  DCHECK(name.is(a2));
-
-  // Probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
-                                               t0, t1, t2);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void LoadIC::GenerateNormal(MacroAssembler* masm) {
   Register dictionary = a0;
   DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
@@ -966,8 +948,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
   // Get the receiver from the stack and probe the stub cache.
   Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
       Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
-                                               t0, t1, t2);
+  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
+                                               name, a3, t0, t1, t2);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
index 6196f26a9d87adb6f5dd8b92f7ccbbb79edc6640..e538712d3f92839d085a1e6f1dcf47518aa1a6a8 100644 (file)
@@ -16,8 +16,8 @@ namespace internal {
 
 
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Flags flags, StubCache::Table table,
-                       Register receiver, Register name,
+                       Code::Flags flags, bool leave_frame,
+                       StubCache::Table table, Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -79,6 +79,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
   }
 #endif
 
+  if (leave_frame) __ LeaveFrame(StackFrame::INTERNAL);
+
   // Jump to the first instruction in the code stub.
   __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(at);
@@ -89,9 +91,9 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
 
 
 void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
-                              Register receiver, Register name,
-                              Register scratch, Register extra, Register extra2,
-                              Register extra3) {
+                              bool leave_frame, Register receiver,
+                              Register name, Register scratch, Register extra,
+                              Register extra2, Register extra3) {
   Isolate* isolate = masm->isolate();
   Label miss;
 
@@ -138,8 +140,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
   __ And(scratch, scratch, Operand(mask));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
-             extra2, extra3);
+  ProbeTable(isolate, masm, flags, leave_frame, kPrimary, receiver, name,
+             scratch, extra, extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ srl(at, name, kCacheIndexShift);
@@ -149,8 +151,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
   __ And(scratch, scratch, Operand(mask2));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
-             extra2, extra3);
+  ProbeTable(isolate, masm, flags, leave_frame, kSecondary, receiver, name,
+             scratch, extra, extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
index fd23f3283e2026a088f3612749384513fa8fe086..0095d14c52b3a0e64e06f328687e54c4e39f5bd9 100644 (file)
@@ -248,24 +248,6 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
 }
 
 
-void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // The return address is in lr.
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register name = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(a1));
-  DCHECK(name.is(a2));
-
-  // Probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
-                                               a4, a5, a6);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void LoadIC::GenerateNormal(MacroAssembler* masm) {
   Register dictionary = a0;
   DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
@@ -975,8 +957,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
   // Get the receiver from the stack and probe the stub cache.
   Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
       Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
-                                               a4, a5, a6);
+  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
+                                               name, a3, a4, a5, a6);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
index 6d3fcb3e1d04f9a311292b1d22773294332f7d4e..272e5bea9b8ab745fbe7363b2a56397f98014ca3 100644 (file)
@@ -16,8 +16,8 @@ namespace internal {
 
 
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Flags flags, StubCache::Table table,
-                       Register receiver, Register name,
+                       Code::Flags flags, bool leave_frame,
+                       StubCache::Table table, Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -79,6 +79,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
   }
 #endif
 
+  if (leave_frame) __ LeaveFrame(StackFrame::INTERNAL);
+
   // Jump to the first instruction in the code stub.
   __ Daddu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(at);
@@ -89,9 +91,9 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
 
 
 void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
-                              Register receiver, Register name,
-                              Register scratch, Register extra, Register extra2,
-                              Register extra3) {
+                              bool leave_frame, Register receiver,
+                              Register name, Register scratch, Register extra,
+                              Register extra2, Register extra3) {
   Isolate* isolate = masm->isolate();
   Label miss;
 
@@ -139,8 +141,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
   __ And(scratch, scratch, Operand(mask));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
-             extra2, extra3);
+  ProbeTable(isolate, masm, flags, leave_frame, kPrimary, receiver, name,
+             scratch, extra, extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ dsrl(at, name, kCacheIndexShift);
@@ -150,8 +152,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
   __ And(scratch, scratch, Operand(mask2));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
-             extra2, extra3);
+  ProbeTable(isolate, masm, flags, leave_frame, kSecondary, receiver, name,
+             scratch, extra, extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
index 9a85eca8102dcb97176932c354a637cf9bc6bb48..978ef7324d540cb773a72e356fbc3ce2b03dbc67 100644 (file)
@@ -30,6 +30,7 @@
 #include "src/base/bits.h"
 #include "src/code-stubs.h"
 #include "src/hydrogen-osr.h"
+#include "src/ic/stub-cache.h"
 #include "src/mips/lithium-codegen-mips.h"
 #include "src/mips/lithium-gap-resolver-mips.h"
 
@@ -3934,6 +3935,34 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
 }
 
 
+void LCodeGen::DoTailCallThroughMegamorphicCache(
+    LTailCallThroughMegamorphicCache* instr) {
+  Register receiver = ToRegister(instr->receiver());
+  Register name = ToRegister(instr->name());
+  DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
+  DCHECK(name.is(LoadDescriptor::NameRegister()));
+  DCHECK(receiver.is(a1));
+  DCHECK(name.is(a2));
+
+  Register scratch = a3;
+  Register extra = t0;
+  Register extra2 = t1;
+  Register extra3 = t2;
+
+  // Important for the tail-call.
+  bool must_teardown_frame = NeedsEagerFrame();
+
+  // The probe will tail call to a handler if found.
+  isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
+                                         must_teardown_frame, receiver, name,
+                                         scratch, extra, extra2, extra3);
+
+  // Tail call to miss if we ended up here.
+  if (must_teardown_frame) __ LeaveFrame(StackFrame::INTERNAL);
+  LoadIC::GenerateMiss(masm());
+}
+
+
 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
   DCHECK(ToRegister(instr->result()).is(v0));
 
index 3b3ca689acb6342c5bfbdf95c2a8cd08c3b21430..2f26ee1d1508cfd264f33bb2cbda1b94ceb974cf 100644 (file)
@@ -1104,6 +1104,19 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
 }
 
 
+LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
+    HTailCallThroughMegamorphicCache* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
+  LOperand* receiver_register =
+      UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
+  LOperand* name_register =
+      UseFixed(instr->name(), LoadDescriptor::NameRegister());
+  // Not marked as call. It can't deoptimize, and it never returns.
+  return new (zone()) LTailCallThroughMegamorphicCache(
+      context, receiver_register, name_register);
+}
+
+
 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* function = UseFixed(instr->function(), a1);
index 1f0776bcbbc1dc6590b9b66bd34f799deab83109..3f18a17927053ddb65466a15ff9a02659782ba6f 100644 (file)
@@ -152,6 +152,7 @@ class LCodeGen;
   V(StringCompareAndBranch)                  \
   V(SubI)                                    \
   V(TaggedToI)                               \
+  V(TailCallThroughMegamorphicCache)         \
   V(ThisFunction)                            \
   V(ToFastProperties)                        \
   V(TransitionElementsKind)                  \
@@ -481,6 +482,27 @@ class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
 };
 
 
+class LTailCallThroughMegamorphicCache FINAL
+    : public LTemplateInstruction<0, 3, 0> {
+ public:
+  explicit LTailCallThroughMegamorphicCache(LOperand* context,
+                                            LOperand* receiver,
+                                            LOperand* name) {
+    inputs_[0] = context;
+    inputs_[1] = receiver;
+    inputs_[2] = name;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+  LOperand* receiver() { return inputs_[1]; }
+  LOperand* name() { return inputs_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
+                               "tail-call-through-megamorphic-cache")
+  DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
+};
+
+
 class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
  public:
   virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
index cc9b85cc3be7c0b26af4358483e9a92663adf223..8a58d4b339194bb4e096f3f0b8499c53f9b469ff 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "src/code-stubs.h"
 #include "src/hydrogen-osr.h"
+#include "src/ic/stub-cache.h"
 #include "src/mips64/lithium-codegen-mips64.h"
 #include "src/mips64/lithium-gap-resolver-mips64.h"
 
@@ -3973,6 +3974,34 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
 }
 
 
+void LCodeGen::DoTailCallThroughMegamorphicCache(
+    LTailCallThroughMegamorphicCache* instr) {
+  Register receiver = ToRegister(instr->receiver());
+  Register name = ToRegister(instr->name());
+  DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
+  DCHECK(name.is(LoadDescriptor::NameRegister()));
+  DCHECK(receiver.is(a1));
+  DCHECK(name.is(a2));
+
+  Register scratch = a3;
+  Register extra = a4;
+  Register extra2 = a5;
+  Register extra3 = a6;
+
+  // Important for the tail-call.
+  bool must_teardown_frame = NeedsEagerFrame();
+
+  // The probe will tail call to a handler if found.
+  isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
+                                         must_teardown_frame, receiver, name,
+                                         scratch, extra, extra2, extra3);
+
+  // Tail call to miss if we ended up here.
+  if (must_teardown_frame) __ LeaveFrame(StackFrame::INTERNAL);
+  LoadIC::GenerateMiss(masm());
+}
+
+
 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
   DCHECK(ToRegister(instr->result()).is(v0));
 
index 742ccdb862ec8e3ac784fac34fcbe86241482792..3afa22d6767a5b5a9663e2cc292091eaee9e982b 100644 (file)
@@ -1104,6 +1104,19 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
 }
 
 
+LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
+    HTailCallThroughMegamorphicCache* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
+  LOperand* receiver_register =
+      UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
+  LOperand* name_register =
+      UseFixed(instr->name(), LoadDescriptor::NameRegister());
+  // Not marked as call. It can't deoptimize, and it never returns.
+  return new (zone()) LTailCallThroughMegamorphicCache(
+      context, receiver_register, name_register);
+}
+
+
 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* function = UseFixed(instr->function(), a1);
index 13f351ea908e0a1ef961a416b21ea2011912e468..464cfa95ad7aaa1ece79c786e538231f5fc49186 100644 (file)
@@ -151,6 +151,7 @@ class LCodeGen;
   V(StringCompareAndBranch)                  \
   V(SubI)                                    \
   V(TaggedToI)                               \
+  V(TailCallThroughMegamorphicCache)         \
   V(ThisFunction)                            \
   V(ToFastProperties)                        \
   V(TransitionElementsKind)                  \
@@ -480,6 +481,27 @@ class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
 };
 
 
+class LTailCallThroughMegamorphicCache FINAL
+    : public LTemplateInstruction<0, 3, 0> {
+ public:
+  explicit LTailCallThroughMegamorphicCache(LOperand* context,
+                                            LOperand* receiver,
+                                            LOperand* name) {
+    inputs_[0] = context;
+    inputs_[1] = receiver;
+    inputs_[2] = name;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+  LOperand* receiver() { return inputs_[1]; }
+  LOperand* name() { return inputs_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
+                               "tail-call-through-megamorphic-cache")
+  DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
+};
+
+
 class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
  public:
   virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {