From: svenpanne Date: Thu, 21 May 2015 14:31:41 +0000 (-0700) Subject: Add a TurboFan skeleton for StringAddStub. X-Git-Tag: upstream/4.7.83~2485 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f91503f25587cf7fdd57edc460fb2349f9ea9c2c;p=platform%2Fupstream%2Fv8.git Add a TurboFan skeleton for StringAddStub. 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} --- diff --git a/src/code-stubs.cc b/src/code-stubs.cc index 774623e..a1437ec 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -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(); } diff --git a/src/code-stubs.h b/src/code-stubs.h index ba673c3..4c683ed 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -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 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 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 static Handle 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 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 {}; + class PretenureFlagBits : public BitField {}; + + 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(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); diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc index 306c347..f6d630f 100644 --- a/src/compiler/arm/code-generator-arm.cc +++ b/src/compiler/arm/code-generator-arm.cc @@ -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(descriptor->JSParameterCount()) diff --git a/src/compiler/arm64/code-generator-arm64.cc b/src/compiler/arm64/code-generator-arm64.cc index 775f519..4c05eb3 100644 --- a/src/compiler/arm64/code-generator-arm64.cc +++ b/src/compiler/arm64/code-generator-arm64.cc @@ -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() diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc index 4cb3d94..16bf92c 100644 --- a/src/compiler/code-generator.cc +++ b/src/compiler/code-generator.cc @@ -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; } diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h index 4ffb3dd..206da70 100644 --- a/src/compiler/code-generator.h +++ b/src/compiler/code-generator.h @@ -184,6 +184,7 @@ class CodeGenerator final : public GapResolver::Assembler { JumpTable* jump_tables_; OutOfLineCode* ools_; int osr_pc_offset_; + bool needs_frame_; }; } // namespace compiler diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc index 0262c2a..de9ac2e 100644 --- a/src/compiler/ia32/code-generator-ia32.cc +++ b/src/compiler/ia32/code-generator-ia32.cc @@ -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() diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h index e9cd4d6..10273a4 100644 --- a/src/compiler/instruction.h +++ b/src/compiler/instruction.h @@ -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); diff --git a/src/compiler/mips/code-generator-mips.cc b/src/compiler/mips/code-generator-mips.cc index 0461190..6e2c4e2 100644 --- a/src/compiler/mips/code-generator-mips.cc +++ b/src/compiler/mips/code-generator-mips.cc @@ -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() diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc index 5314de7..caf6784 100644 --- a/src/compiler/mips64/code-generator-mips64.cc +++ b/src/compiler/mips64/code-generator-mips64.cc @@ -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() diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/ppc/code-generator-ppc.cc index bdebd30..d7b0383 100644 --- a/src/compiler/ppc/code-generator-ppc.cc +++ b/src/compiler/ppc/code-generator-ppc.cc @@ -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(descriptor->JSParameterCount()) : 0; diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index 0f1e959..2105d66 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -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() diff --git a/src/globals.h b/src/globals.h index 7619831..00665e3 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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 diff --git a/src/runtime.js b/src/runtime.js index d89715a..86db495 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -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 diff --git a/test/cctest/compiler/test-run-stubs.cc b/test/cctest/compiler/test-run-stubs.cc index 5c012a3..5baa79a 100644 --- a/test/cctest/compiler/test-run-stubs.cc +++ b/test/cctest/compiler/test-run-stubs.cc @@ -106,4 +106,42 @@ TEST(RunStringLengthTFStub) { CHECK_EQ(static_cast(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 = 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 u = Unique::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 leftArg = ft.Val("links"); + Handle rightArg = ft.Val("rechts"); + Handle result = ft.Call(leftArg, rightArg).ToHandleChecked(); + CHECK(String::Equals(ft.Val("linksrechts"), Handle::cast(result))); +} + #endif // V8_TURBOFAN_TARGET