Add a TurboFan skeleton for StringAddStub.
authorsvenpanne <svenpanne@chromium.org>
Thu, 21 May 2015 14:31:41 +0000 (07:31 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 21 May 2015 14:31:25 +0000 (14:31 +0000)
Currently the stub simply calls out to the runtime, this will be
improved in a later CLs. The current state at least avoids bit-rot and
later merging horror.

Fixes frame construction logic for stubs, too, and contains quite a few
tiny cleanups in stub-land.

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

Cr-Commit-Position: refs/heads/master@{#28555}

15 files changed:
src/code-stubs.cc
src/code-stubs.h
src/compiler/arm/code-generator-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/code-generator.cc
src/compiler/code-generator.h
src/compiler/ia32/code-generator-ia32.cc
src/compiler/instruction.h
src/compiler/mips/code-generator-mips.cc
src/compiler/mips64/code-generator-mips64.cc
src/compiler/ppc/code-generator-ppc.cc
src/compiler/x64/code-generator-x64.cc
src/globals.h
src/runtime.js
test/cctest/compiler/test-run-stubs.cc

index 774623e..a1437ec 100644 (file)
@@ -315,18 +315,29 @@ void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
 }
 
 
-void StringAddStub::PrintBaseName(std::ostream& os) const {  // NOLINT
-  os << "StringAddStub";
-  if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
-    os << "_CheckBoth";
-  } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
-    os << "_CheckLeft";
-  } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
-    os << "_CheckRight";
-  }
-  if (pretenure_flag() == TENURED) {
-    os << "_Tenured";
+std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) {
+  switch (flags) {
+    case STRING_ADD_CHECK_NONE:
+      return os << "CheckNone";
+    case STRING_ADD_CHECK_LEFT:
+      return os << "CheckLeft";
+    case STRING_ADD_CHECK_RIGHT:
+      return os << "CheckRight";
+    case STRING_ADD_CHECK_BOTH:
+      return os << "CheckBoth";
   }
+  UNREACHABLE();
+  return os;
+}
+
+
+void StringAddStub::PrintBaseName(std::ostream& os) const {  // NOLINT
+  os << "StringAddStub_" << flags() << "_" << pretenure_flag();
+}
+
+
+void StringAddTFStub::PrintBaseName(std::ostream& os) const {  // NOLINT
+  os << "StringAddTFStub_" << flags() << "_" << pretenure_flag();
 }
 
 
index ba673c3..4c683ed 100644 (file)
@@ -89,6 +89,7 @@ namespace internal {
   V(LoadIC)                                 \
   /* TurboFanCodeStubs */                   \
   V(StringLengthTF)                         \
+  V(StringAddTF)                            \
   V(MathFloor)                              \
   /* IC Handler stubs */                    \
   V(ArrayBufferViewLoadField)               \
@@ -354,17 +355,9 @@ struct FakeStubForTesting : public CodeStub {
   Handle<Code> GenerateCode() override;                               \
   DEFINE_CODE_STUB(NAME, SUPER)
 
-#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER, DESC, STACK_PARAMS)     \
- public:                                                               \
-  NAME##Stub(Isolate* isolate) : SUPER(isolate) {}                     \
-  CallInterfaceDescriptor GetCallInterfaceDescriptor() override {      \
-    return DESC(isolate());                                            \
-  };                                                                   \
-  virtual const char* GetFunctionName() const override {               \
-    return #NAME "_STUB";                                              \
-  }                                                                    \
-  int GetStackParameterCount() const override { return STACK_PARAMS; } \
-  Code::StubType GetStubType() const override { return Code::FAST; }   \
+#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                           \
+ public:                                                                 \
+  const char* GetFunctionName() const override { return #NAME "_STUB"; } \
   DEFINE_CODE_STUB(NAME, SUPER)
 
 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
@@ -394,8 +387,6 @@ class PlatformCodeStub : public CodeStub {
   // Retrieve the code for the stub. Generate the code if needed.
   Handle<Code> GenerateCode() override;
 
-  Code::Kind GetCodeKind() const override { return Code::STUB; }
-
  protected:
   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
 
@@ -494,8 +485,6 @@ class HydrogenCodeStub : public CodeStub {
     INITIALIZED
   };
 
-  Code::Kind GetCodeKind() const override { return Code::STUB; }
-
   template<class SubClass>
   static Handle<Code> GetUninitialized(Isolate* isolate) {
     SubClass::GenerateAheadOfTime(isolate);
@@ -539,11 +528,11 @@ class HydrogenCodeStub : public CodeStub {
 
 class TurboFanCodeStub : public CodeStub {
  public:
-  Code::Kind GetCodeKind() const override { return Code::STUB; }
-
   // Retrieve the code for the stub. Generate the code if needed.
   Handle<Code> GenerateCode() override;
 
+  Code::StubType GetStubType() const override { return Code::FAST; }
+
   virtual const char* GetFunctionName() const = 0;
 
  protected:
@@ -621,19 +610,68 @@ class NopRuntimeCallHelper : public RuntimeCallHelper {
 
 
 class MathFloorStub : public TurboFanCodeStub {
-  DEFINE_TURBOFAN_CODE_STUB(MathFloor, TurboFanCodeStub,
-                            MathRoundVariantDescriptor, 1);
+ public:
+  explicit MathFloorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+  int GetStackParameterCount() const override { return 1; }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(MathRoundVariant);
+  DEFINE_TURBOFAN_CODE_STUB(MathFloor, TurboFanCodeStub);
 };
 
 
 class StringLengthTFStub : public TurboFanCodeStub {
-  DEFINE_TURBOFAN_CODE_STUB(StringLengthTF, TurboFanCodeStub,
-                            LoadWithVectorDescriptor, 0);
-
  public:
+  explicit StringLengthTFStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
   InlineCacheState GetICState() const override { return MONOMORPHIC; }
   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
+  DEFINE_TURBOFAN_CODE_STUB(StringLengthTF, TurboFanCodeStub);
+};
+
+
+enum StringAddFlags {
+  // Omit both parameter checks.
+  STRING_ADD_CHECK_NONE = 0,
+  // Check left parameter.
+  STRING_ADD_CHECK_LEFT = 1 << 0,
+  // Check right parameter.
+  STRING_ADD_CHECK_RIGHT = 1 << 1,
+  // Check both parameters.
+  STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
+};
+
+
+std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags);
+
+
+class StringAddTFStub : public TurboFanCodeStub {
+ public:
+  StringAddTFStub(Isolate* isolate, StringAddFlags flags,
+                  PretenureFlag pretenure_flag)
+      : TurboFanCodeStub(isolate) {
+    minor_key_ = StringAddFlagsBits::encode(flags) |
+                 PretenureFlagBits::encode(pretenure_flag);
+  }
+
+  StringAddFlags flags() const {
+    return StringAddFlagsBits::decode(MinorKey());
+  }
+
+  PretenureFlag pretenure_flag() const {
+    return PretenureFlagBits::decode(MinorKey());
+  }
+
+ private:
+  class StringAddFlagsBits : public BitField<StringAddFlags, 0, 2> {};
+  class PretenureFlagBits : public BitField<PretenureFlag, 2, 1> {};
+
+  void PrintBaseName(std::ostream& os) const override;  // NOLINT
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
+  DEFINE_TURBOFAN_CODE_STUB(StringAddTF, TurboFanCodeStub);
 };
 
 
@@ -1473,18 +1511,6 @@ class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
 };
 
 
-enum StringAddFlags {
-  // Omit both parameter checks.
-  STRING_ADD_CHECK_NONE = 0,
-  // Check left parameter.
-  STRING_ADD_CHECK_LEFT = 1 << 0,
-  // Check right parameter.
-  STRING_ADD_CHECK_RIGHT = 1 << 1,
-  // Check both parameters.
-  STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
-};
-
-
 class StringAddStub final : public HydrogenCodeStub {
  public:
   StringAddStub(Isolate* isolate, StringAddFlags flags,
@@ -1791,7 +1817,7 @@ class RestParamAccessStub: public PlatformCodeStub {
  private:
   void GenerateNew(MacroAssembler* masm);
 
-  virtual void PrintName(std::ostream& os) const override;  // NOLINT
+  void PrintName(std::ostream& os) const override;  // NOLINT
 
   DEFINE_PLATFORM_CODE_STUB(RestParamAccess, PlatformCodeStub);
 };
@@ -2177,11 +2203,11 @@ class LoadICStub : public PlatformCodeStub {
 
   void GenerateForTrampoline(MacroAssembler* masm);
 
-  virtual Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
+  Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
 
-  virtual InlineCacheState GetICState() const final override { return DEFAULT; }
+  InlineCacheState GetICState() const final override { return DEFAULT; }
 
-  virtual ExtraICState GetExtraICState() const final override {
+  ExtraICState GetExtraICState() const final override {
     return static_cast<ExtraICState>(minor_key_);
   }
 
@@ -2199,11 +2225,9 @@ class KeyedLoadICStub : public PlatformCodeStub {
 
   void GenerateForTrampoline(MacroAssembler* masm);
 
-  virtual Code::Kind GetCodeKind() const override {
-    return Code::KEYED_LOAD_IC;
-  }
+  Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
 
-  virtual InlineCacheState GetICState() const final override { return DEFAULT; }
+  InlineCacheState GetICState() const final override { return DEFAULT; }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
index 306c347..f6d630f 100644 (file)
@@ -952,7 +952,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -997,7 +997,7 @@ void CodeGenerator::AssembleReturn() {
     }
     __ LeaveFrame(StackFrame::MANUAL);
     __ Ret();
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     __ LeaveFrame(StackFrame::MANUAL);
     int pop_count = descriptor->IsJSFunctionCall()
                         ? static_cast<int>(descriptor->JSParameterCount())
index 775f519..4c05eb3 100644 (file)
@@ -1078,7 +1078,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ SetStackPointer(jssp);
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
@@ -1127,7 +1127,7 @@ void CodeGenerator::AssembleReturn() {
     __ Mov(csp, fp);
     __ Pop(fp, lr);
     __ Ret();
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     __ Mov(jssp, fp);
     __ Pop(fp, lr);
     int pop_count = descriptor->IsJSFunctionCall()
index 4cb3d94..16bf92c 100644 (file)
@@ -49,7 +49,8 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
       last_lazy_deopt_pc_(0),
       jump_tables_(nullptr),
       ools_(nullptr),
-      osr_pc_offset_(-1) {
+      osr_pc_offset_(-1),
+      needs_frame_(frame->GetSpillSlotCount() > 0 || code->ContainsCall()) {
   for (int i = 0; i < code->InstructionBlockCount(); ++i) {
     new (&labels_[i]) Label;
   }
index 4ffb3dd..206da70 100644 (file)
@@ -184,6 +184,7 @@ class CodeGenerator final : public GapResolver::Assembler {
   JumpTable* jump_tables_;
   OutOfLineCode* ools_;
   int osr_pc_offset_;
+  bool needs_frame_;
 };
 
 }  // namespace compiler
index 0262c2a..de9ac2e 100644 (file)
@@ -1256,7 +1256,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -1310,7 +1310,7 @@ void CodeGenerator::AssembleReturn() {
       __ pop(ebp);       // Pop caller's frame pointer.
       __ ret(0);
     }
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
     __ pop(ebp);       // Pop caller's frame pointer.
     int pop_count = descriptor->IsJSFunctionCall()
index e9cd4d6..10273a4 100644 (file)
@@ -1156,6 +1156,13 @@ class InstructionSequence final : public ZoneObject {
                          SourcePosition* result) const;
   void SetSourcePosition(const Instruction* instr, SourcePosition value);
 
+  bool ContainsCall() const {
+    for (Instruction* instr : instructions_) {
+      if (instr->IsCall()) return true;
+    }
+    return false;
+  }
+
  private:
   friend std::ostream& operator<<(std::ostream& os,
                                   const PrintableInstructionSequence& code);
index 0461190..6e2c4e2 100644 (file)
@@ -1075,7 +1075,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -1121,7 +1121,7 @@ void CodeGenerator::AssembleReturn() {
     __ mov(sp, fp);
     __ Pop(ra, fp);
     __ Ret();
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     __ mov(sp, fp);
     __ Pop(ra, fp);
     int pop_count = descriptor->IsJSFunctionCall()
index 5314de7..caf6784 100644 (file)
@@ -1141,7 +1141,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -1187,7 +1187,7 @@ void CodeGenerator::AssembleReturn() {
     __ mov(sp, fp);
     __ Pop(ra, fp);
     __ Ret();
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     __ mov(sp, fp);
     __ Pop(ra, fp);
     int pop_count = descriptor->IsJSFunctionCall()
index bdebd30..d7b0383 100644 (file)
@@ -1284,7 +1284,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -1330,7 +1330,7 @@ void CodeGenerator::AssembleReturn() {
     }
     __ LeaveFrame(StackFrame::MANUAL);
     __ Ret();
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     int pop_count = descriptor->IsJSFunctionCall()
                         ? static_cast<int>(descriptor->JSParameterCount())
                         : 0;
index 0f1e959..2105d66 100644 (file)
@@ -1451,7 +1451,7 @@ void CodeGenerator::AssemblePrologue() {
     __ Prologue(info->IsCodePreAgingActive());
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
-  } else if (stack_slots > 0) {
+  } else if (needs_frame_) {
     __ StubPrologue();
     frame()->SetRegisterSaveAreaSize(
         StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -1504,7 +1504,7 @@ void CodeGenerator::AssembleReturn() {
       __ popq(rbp);       // Pop caller's frame pointer.
       __ ret(0);
     }
-  } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) {
+  } else if (descriptor->IsJSFunctionCall() || needs_frame_) {
     __ movq(rsp, rbp);  // Move stack pointer back to frame pointer.
     __ popq(rbp);       // Pop caller's frame pointer.
     int pop_count = descriptor->IsJSFunctionCall()
index 7619831..00665e3 100644 (file)
@@ -240,7 +240,7 @@ enum LanguageMode {
 };
 
 
-inline std::ostream& operator<<(std::ostream& os, LanguageMode mode) {
+inline std::ostream& operator<<(std::ostream& os, const LanguageMode& mode) {
   switch (mode) {
     case SLOPPY:
       return os << "sloppy";
@@ -446,6 +446,17 @@ enum AllocationAlignment { kWordAligned, kDoubleAligned, kDoubleUnaligned };
 // allows).
 enum PretenureFlag { NOT_TENURED, TENURED };
 
+inline std::ostream& operator<<(std::ostream& os, const PretenureFlag& flag) {
+  switch (flag) {
+    case NOT_TENURED:
+      return os << "NotTenured";
+    case TENURED:
+      return os << "Tenured";
+  }
+  UNREACHABLE();
+  return os;
+}
+
 enum MinimumCapacity {
   USE_DEFAULT_MINIMUM_CAPACITY,
   USE_CUSTOM_MINIMUM_CAPACITY
index d89715a..86db495 100644 (file)
@@ -65,6 +65,7 @@ var TO_STRING;
 var TO_NAME;
 
 var StringLengthTF_STUB;
+var StringAddTF_STUB;
 var MathFloor_STUB;
 
 var $defaultNumber;
@@ -772,6 +773,10 @@ StringLengthTF_STUB = function StringLengthTF_STUB(receiver, name, i, v) {
   return %_StringGetLength(%_JSValueGetValue(receiver));
 }
 
+StringAddTF_STUB = function StringAddTF_STUB(left, right) {
+  return %StringAdd(left, right);
+}
+
 MathFloor_STUB = function MathFloor_STUB(f, i, v) {
   // |f| is calling function's JSFunction
   // |i| is TypeFeedbackVector slot # of callee's CallIC for Math.floor call
index 5c012a3..5baa79a 100644 (file)
@@ -106,4 +106,42 @@ TEST(RunStringLengthTFStub) {
   CHECK_EQ(static_cast<int>(strlen(testString)), Smi::cast(*result)->value());
 }
 
+
+TEST(RunStringAddTFStub) {
+  HandleAndZoneScope scope;
+  Isolate* isolate = scope.main_isolate();
+  Zone* zone = scope.main_zone();
+
+  // Create code and an accompanying descriptor.
+  StringAddTFStub stub(isolate, STRING_ADD_CHECK_BOTH, NOT_TENURED);
+  Handle<Code> code = stub.GenerateCode();
+  CompilationInfo info(&stub, isolate, zone);
+  CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
+
+  // Create a function to call the code using the descriptor.
+  Graph graph(zone);
+  CommonOperatorBuilder common(zone);
+  // FunctionTester (ab)uses a 2-argument function
+  Node* start = graph.NewNode(common.Start(2));
+  // Parameter 0 is the receiver
+  Node* leftParam = graph.NewNode(common.Parameter(1), start);
+  Node* rightParam = graph.NewNode(common.Parameter(2), start);
+  Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code);
+  Node* theCode = graph.NewNode(common.HeapConstant(u));
+  Node* dummyContext = graph.NewNode(common.NumberConstant(0.0));
+  Node* call = graph.NewNode(common.Call(descriptor), theCode, leftParam,
+                             rightParam, dummyContext, start, start);
+  Node* ret = graph.NewNode(common.Return(), call, call, start);
+  Node* end = graph.NewNode(common.End(), ret);
+  graph.SetStart(start);
+  graph.SetEnd(end);
+  FunctionTester ft(&graph);
+
+  // Actuall call through to the stub, verifying its result.
+  Handle<String> leftArg = ft.Val("links");
+  Handle<String> rightArg = ft.Val("rechts");
+  Handle<Object> result = ft.Call(leftArg, rightArg).ToHandleChecked();
+  CHECK(String::Equals(ft.Val("linksrechts"), Handle<String>::cast(result)));
+}
+
 #endif  // V8_TURBOFAN_TARGET