Commit f91503f2 authored by svenpanne's avatar svenpanne Committed by Commit bot

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}
parent 9d9acf55
......@@ -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();
}
......
......@@ -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);
......
......@@ -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())
......
......@@ -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()
......
......@@ -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;
}
......
......@@ -184,6 +184,7 @@ class CodeGenerator final : public GapResolver::Assembler {
JumpTable* jump_tables_;
OutOfLineCode* ools_;
int osr_pc_offset_;
bool needs_frame_;
};
} // namespace compiler
......
......@@ -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()
......
......@@ -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);
......
......@@ -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()
......
......@@ -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()
......
......@@ -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;
......
......@@ -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()
......
......@@ -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
......
......@@ -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
......
......@@ -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
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