Commit 62bc168d authored by bmeurer's avatar bmeurer Committed by Commit bot

[compiler] Initial TurboFan code stubs for abstract relational comparison.

This adds new code stubs for abstract relational comparison,
namely LessThanStub, LessThanOrEqualStub, GreaterThanStub and
GreaterThanOrEqualStub, and hooks them up for Ignition and TurboFan.
These stubs implement the full compare operation without any
unpredictable bailouts. Currently they still go to C++ for string
comparisons, and also use the %ToPrimitive_Number runtime entry, as
we still lack a stub for the ToPrimitive operation. These issues
will be addressed separately in follow-up CLs.

Drive-by-fix: Add support for deferred code in the RawMachineAssembler
and CodeStubAssembler. A block can be marked as deferred by marking its
Label as deferred, which will then make the register allocator penalize
this block and prefer better register assignments for the other blocks.

R=epertoso@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34463}
parent d61b8cee
...@@ -194,6 +194,30 @@ Callable CodeFactory::RegExpExec(Isolate* isolate) { ...@@ -194,6 +194,30 @@ Callable CodeFactory::RegExpExec(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
} }
// static
Callable CodeFactory::LessThan(Isolate* isolate) {
LessThanStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::LessThanOrEqual(Isolate* isolate) {
LessThanOrEqualStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::GreaterThan(Isolate* isolate) {
GreaterThanStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::GreaterThanOrEqual(Isolate* isolate) {
GreaterThanOrEqualStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static // static
Callable CodeFactory::StrictEqual(Isolate* isolate) { Callable CodeFactory::StrictEqual(Isolate* isolate) {
StrictEqualStub stub(isolate); StrictEqualStub stub(isolate);
......
...@@ -75,6 +75,10 @@ class CodeFactory final { ...@@ -75,6 +75,10 @@ class CodeFactory final {
static Callable RegExpConstructResult(Isolate* isolate); static Callable RegExpConstructResult(Isolate* isolate);
static Callable RegExpExec(Isolate* isolate); static Callable RegExpExec(Isolate* isolate);
static Callable LessThan(Isolate* isolate);
static Callable LessThanOrEqual(Isolate* isolate);
static Callable GreaterThan(Isolate* isolate);
static Callable GreaterThanOrEqual(Isolate* isolate);
static Callable StrictEqual(Isolate* isolate); static Callable StrictEqual(Isolate* isolate);
static Callable StrictNotEqual(Isolate* isolate); static Callable StrictNotEqual(Isolate* isolate);
......
This diff is collapsed.
...@@ -101,6 +101,10 @@ namespace internal { ...@@ -101,6 +101,10 @@ namespace internal {
V(AllocateHeapNumber) \ V(AllocateHeapNumber) \
V(AllocateMutableHeapNumber) \ V(AllocateMutableHeapNumber) \
V(StringLength) \ V(StringLength) \
V(LessThan) \
V(LessThanOrEqual) \
V(GreaterThan) \
V(GreaterThanOrEqual) \
V(StrictEqual) \ V(StrictEqual) \
V(StrictNotEqual) \ V(StrictNotEqual) \
V(StringEqual) \ V(StringEqual) \
...@@ -351,11 +355,10 @@ class CodeStub BASE_EMBEDDED { ...@@ -351,11 +355,10 @@ class CodeStub BASE_EMBEDDED {
Handle<Code> GenerateCode() override; \ Handle<Code> GenerateCode() override; \
DEFINE_CODE_STUB(NAME, SUPER) DEFINE_CODE_STUB(NAME, SUPER)
#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \ #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
public: \ public: \
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ void GenerateAssembly(compiler::CodeStubAssembler* assembler) \
return DESC##Descriptor(isolate()); \ const override; \
}; \
DEFINE_CODE_STUB(NAME, SUPER) DEFINE_CODE_STUB(NAME, SUPER)
#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \ #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
...@@ -629,60 +632,81 @@ class StringLengthStub : public TurboFanCodeStub { ...@@ -629,60 +632,81 @@ class StringLengthStub : public TurboFanCodeStub {
InlineCacheState GetICState() const override { return MONOMORPHIC; } InlineCacheState GetICState() const override { return MONOMORPHIC; }
ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
DEFINE_CODE_STUB(StringLength, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
};
class LessThanStub final : public TurboFanCodeStub {
public:
explicit LessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_TURBOFAN_CODE_STUB(LessThan, TurboFanCodeStub);
};
class LessThanOrEqualStub final : public TurboFanCodeStub {
public:
explicit LessThanOrEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_TURBOFAN_CODE_STUB(LessThanOrEqual, TurboFanCodeStub);
};
class GreaterThanStub final : public TurboFanCodeStub {
public:
explicit GreaterThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_TURBOFAN_CODE_STUB(GreaterThan, TurboFanCodeStub);
};
class GreaterThanOrEqualStub final : public TurboFanCodeStub {
public:
explicit GreaterThanOrEqualStub(Isolate* isolate)
: TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_TURBOFAN_CODE_STUB(GreaterThanOrEqual, TurboFanCodeStub);
}; };
class StrictEqualStub final : public TurboFanCodeStub { class StrictEqualStub final : public TurboFanCodeStub {
public: public:
explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const final;
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare); DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_CODE_STUB(StrictEqual, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StrictEqual, TurboFanCodeStub);
}; };
class StrictNotEqualStub final : public TurboFanCodeStub { class StrictNotEqualStub final : public TurboFanCodeStub {
public: public:
explicit StrictNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit StrictNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const final;
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare); DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_CODE_STUB(StrictNotEqual, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StrictNotEqual, TurboFanCodeStub);
}; };
class StringEqualStub final : public TurboFanCodeStub { class StringEqualStub final : public TurboFanCodeStub {
public: public:
explicit StringEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit StringEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const final;
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare); DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_CODE_STUB(StringEqual, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StringEqual, TurboFanCodeStub);
}; };
class StringNotEqualStub final : public TurboFanCodeStub { class StringNotEqualStub final : public TurboFanCodeStub {
public: public:
explicit StringNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit StringNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const final;
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare); DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_CODE_STUB(StringNotEqual, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StringNotEqual, TurboFanCodeStub);
}; };
class ToBooleanStub final : public TurboFanCodeStub { class ToBooleanStub final : public TurboFanCodeStub {
public: public:
explicit ToBooleanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit ToBooleanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const final;
DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean); DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
DEFINE_CODE_STUB(ToBoolean, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(ToBoolean, TurboFanCodeStub);
}; };
enum StringAddFlags { enum StringAddFlags {
......
...@@ -163,6 +163,14 @@ Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); } ...@@ -163,6 +163,14 @@ Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); }
Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); } Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); }
Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) {
return IntPtrLessThan(a, b);
}
Node* CodeStubAssembler::SmiLessThanOrEqual(Node* a, Node* b) {
return IntPtrLessThanOrEqual(a, b);
}
#define DEFINE_CODE_STUB_ASSEMBER_BINARY_OP(name) \ #define DEFINE_CODE_STUB_ASSEMBER_BINARY_OP(name) \
Node* CodeStubAssembler::name(Node* a, Node* b) { \ Node* CodeStubAssembler::name(Node* a, Node* b) { \
return raw_assembler_->name(a, b); \ return raw_assembler_->name(a, b); \
...@@ -416,6 +424,27 @@ Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, ...@@ -416,6 +424,27 @@ Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
raw_assembler_->Int32Constant(shift)); raw_assembler_->Int32Constant(shift));
} }
void CodeStubAssembler::BranchIfSmiLessThan(Node* a, Node* b, Label* if_true,
Label* if_false) {
Label if_lessthan(this), if_notlessthan(this);
Branch(SmiLessThan(a, b), &if_lessthan, &if_notlessthan);
Bind(&if_lessthan);
Goto(if_true);
Bind(&if_notlessthan);
Goto(if_false);
}
void CodeStubAssembler::BranchIfSmiLessThanOrEqual(Node* a, Node* b,
Label* if_true,
Label* if_false) {
Label if_lessthanorequal(this), if_notlessthanorequal(this);
Branch(SmiLessThanOrEqual(a, b), &if_lessthanorequal, &if_notlessthanorequal);
Bind(&if_lessthanorequal);
Goto(if_true);
Bind(&if_notlessthanorequal);
Goto(if_false);
}
void CodeStubAssembler::BranchIfFloat64Equal(Node* a, Node* b, Label* if_true, void CodeStubAssembler::BranchIfFloat64Equal(Node* a, Node* b, Label* if_true,
Label* if_false) { Label* if_false) {
Label if_equal(this), if_notequal(this); Label if_equal(this), if_notequal(this);
...@@ -426,6 +455,52 @@ void CodeStubAssembler::BranchIfFloat64Equal(Node* a, Node* b, Label* if_true, ...@@ -426,6 +455,52 @@ void CodeStubAssembler::BranchIfFloat64Equal(Node* a, Node* b, Label* if_true,
Goto(if_false); Goto(if_false);
} }
void CodeStubAssembler::BranchIfFloat64LessThan(Node* a, Node* b,
Label* if_true,
Label* if_false) {
Label if_lessthan(this), if_notlessthan(this);
Branch(Float64LessThan(a, b), &if_lessthan, &if_notlessthan);
Bind(&if_lessthan);
Goto(if_true);
Bind(&if_notlessthan);
Goto(if_false);
}
void CodeStubAssembler::BranchIfFloat64LessThanOrEqual(Node* a, Node* b,
Label* if_true,
Label* if_false) {
Label if_lessthanorequal(this), if_notlessthanorequal(this);
Branch(Float64LessThanOrEqual(a, b), &if_lessthanorequal,
&if_notlessthanorequal);
Bind(&if_lessthanorequal);
Goto(if_true);
Bind(&if_notlessthanorequal);
Goto(if_false);
}
void CodeStubAssembler::BranchIfFloat64GreaterThan(Node* a, Node* b,
Label* if_true,
Label* if_false) {
Label if_greaterthan(this), if_notgreaterthan(this);
Branch(Float64GreaterThan(a, b), &if_greaterthan, &if_notgreaterthan);
Bind(&if_greaterthan);
Goto(if_true);
Bind(&if_notgreaterthan);
Goto(if_false);
}
void CodeStubAssembler::BranchIfFloat64GreaterThanOrEqual(Node* a, Node* b,
Label* if_true,
Label* if_false) {
Label if_greaterthanorequal(this), if_notgreaterthanorequal(this);
Branch(Float64GreaterThanOrEqual(a, b), &if_greaterthanorequal,
&if_notgreaterthanorequal);
Bind(&if_greaterthanorequal);
Goto(if_true);
Bind(&if_notgreaterthanorequal);
Goto(if_false);
}
Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target, Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
Node** args) { Node** args) {
CallPrologue(); CallPrologue();
...@@ -515,6 +590,12 @@ Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id, ...@@ -515,6 +590,12 @@ Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
context); context);
} }
Node* CodeStubAssembler::CallStub(Callable const& callable, Node* context,
Node* arg1, size_t result_size) {
Node* target = HeapConstant(callable.code());
return CallStub(callable.descriptor(), target, context, arg1, result_size);
}
Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor, Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
Node* target, Node* context, Node* arg1, Node* target, Node* context, Node* arg1,
size_t result_size) { size_t result_size) {
...@@ -709,27 +790,20 @@ bool CodeStubAssembler::Variable::IsBound() const { ...@@ -709,27 +790,20 @@ bool CodeStubAssembler::Variable::IsBound() const {
return impl_->value_ != nullptr; return impl_->value_ != nullptr;
} }
CodeStubAssembler::Label::Label(CodeStubAssembler* assembler)
: bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
label_ = new (buffer) RawMachineLabel();
}
CodeStubAssembler::Label::Label(CodeStubAssembler* assembler, CodeStubAssembler::Label::Label(CodeStubAssembler* assembler,
int merged_value_count, int merged_value_count,
CodeStubAssembler::Variable** merged_variables) CodeStubAssembler::Variable** merged_variables,
CodeStubAssembler::Label::Type type)
: bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) { : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
void* buffer = assembler->zone()->New(sizeof(RawMachineLabel)); void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
label_ = new (buffer) RawMachineLabel(); label_ = new (buffer)
RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
: RawMachineLabel::kNonDeferred);
for (int i = 0; i < merged_value_count; ++i) { for (int i = 0; i < merged_value_count; ++i) {
variable_phis_[merged_variables[i]->impl_] = nullptr; variable_phis_[merged_variables[i]->impl_] = nullptr;
} }
} }
CodeStubAssembler::Label::Label(CodeStubAssembler* assembler,
CodeStubAssembler::Variable* merged_variable)
: CodeStubAssembler::Label(assembler, 1, &merged_variable) {}
void CodeStubAssembler::Label::MergeVariables() { void CodeStubAssembler::Label::MergeVariables() {
++merge_count_; ++merge_count_;
for (auto var : assembler_->variables_) { for (auto var : assembler_->variables_) {
...@@ -760,16 +834,17 @@ void CodeStubAssembler::Label::MergeVariables() { ...@@ -760,16 +834,17 @@ void CodeStubAssembler::Label::MergeVariables() {
assembler_->raw_assembler_->AppendPhiInput(phi->second, node); assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
} else { } else {
auto i = variable_merges_.find(var); auto i = variable_merges_.find(var);
USE(i); if (i != variable_merges_.end()) {
// If the following assert fires, then you've declared a variable that // If the following assert fires, then you've declared a variable that
// has the same bound value along all paths up until the point you bound // has the same bound value along all paths up until the point you
// this label, but then later merged a path with a new value for the // bound this label, but then later merged a path with a new value for
// variable after the label bind (it's not possible to add phis to the // the variable after the label bind (it's not possible to add phis to
// bound label after the fact, just make sure to list the variable in // the bound label after the fact, just make sure to list the variable
// the label's constructor's list of merged variables). // in the label's constructor's list of merged variables).
DCHECK(find_if(i->second.begin(), i->second.end(), DCHECK(find_if(i->second.begin(), i->second.end(),
[node](Node* e) -> bool { return node != e; }) == [node](Node* e) -> bool { return node != e; }) ==
i->second.end()); i->second.end());
}
} }
} }
} }
......
...@@ -39,13 +39,17 @@ class Schedule; ...@@ -39,13 +39,17 @@ class Schedule;
V(Float64Equal) \ V(Float64Equal) \
V(Float64LessThan) \ V(Float64LessThan) \
V(Float64LessThanOrEqual) \ V(Float64LessThanOrEqual) \
V(Float64GreaterThan) \
V(Float64GreaterThanOrEqual) \
V(IntPtrAdd) \ V(IntPtrAdd) \
V(IntPtrSub) \ V(IntPtrSub) \
V(Int32Add) \ V(Int32Add) \
V(Int32Sub) \ V(Int32Sub) \
V(Int32Mul) \ V(Int32Mul) \
V(Int32GreaterThan) \
V(Int32GreaterThanOrEqual) \ V(Int32GreaterThanOrEqual) \
V(Int32LessThan) \ V(Int32LessThan) \
V(Int32LessThanOrEqual) \
V(WordEqual) \ V(WordEqual) \
V(WordNotEqual) \ V(WordNotEqual) \
V(WordOr) \ V(WordOr) \
...@@ -72,6 +76,8 @@ class Schedule; ...@@ -72,6 +76,8 @@ class Schedule;
V(Word64Shr) \ V(Word64Shr) \
V(Word64Sar) \ V(Word64Sar) \
V(Word64Ror) \ V(Word64Ror) \
V(IntPtrLessThan) \
V(IntPtrLessThanOrEqual) \
V(UintPtrGreaterThanOrEqual) V(UintPtrGreaterThanOrEqual)
#define CODE_STUB_ASSEMBLER_UNARY_OP_LIST(V) \ #define CODE_STUB_ASSEMBLER_UNARY_OP_LIST(V) \
...@@ -202,6 +208,9 @@ class CodeStubAssembler { ...@@ -202,6 +208,9 @@ class CodeStubAssembler {
Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context, Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
Node* arg1, Node* arg2, Node* arg3, Node* arg4); Node* arg1, Node* arg2, Node* arg3, Node* arg4);
Node* CallStub(Callable const& callable, Node* context, Node* arg1,
size_t result_size = 1);
Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target, Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
Node* context, Node* arg1, size_t result_size = 1); Node* context, Node* arg1, size_t result_size = 1);
Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target, Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
...@@ -242,6 +251,8 @@ class CodeStubAssembler { ...@@ -242,6 +251,8 @@ class CodeStubAssembler {
// Smi operations. // Smi operations.
Node* SmiAdd(Node* a, Node* b); Node* SmiAdd(Node* a, Node* b);
Node* SmiEqual(Node* a, Node* b); Node* SmiEqual(Node* a, Node* b);
Node* SmiLessThan(Node* a, Node* b);
Node* SmiLessThanOrEqual(Node* a, Node* b);
// Load a value from the root array. // Load a value from the root array.
Node* LoadRoot(Heap::RootListIndex root_index); Node* LoadRoot(Heap::RootListIndex root_index);
...@@ -281,18 +292,31 @@ class CodeStubAssembler { ...@@ -281,18 +292,31 @@ class CodeStubAssembler {
// Branching helpers. // Branching helpers.
// TODO(danno): Can we be more cleverish wrt. edge-split? // TODO(danno): Can we be more cleverish wrt. edge-split?
void BranchIfSmiLessThan(Node* a, Node* b, Label* if_true, Label* if_false);
void BranchIfSmiLessThanOrEqual(Node* a, Node* b, Label* if_true,
Label* if_false);
void BranchIfFloat64Equal(Node* a, Node* b, Label* if_true, Label* if_false); void BranchIfFloat64Equal(Node* a, Node* b, Label* if_true, Label* if_false);
void BranchIfFloat64LessThan(Node* a, Node* b, Label* if_true,
Label* if_false);
void BranchIfFloat64LessThanOrEqual(Node* a, Node* b, Label* if_true,
Label* if_false);
void BranchIfFloat64GreaterThan(Node* a, Node* b, Label* if_true,
Label* if_false);
void BranchIfFloat64GreaterThanOrEqual(Node* a, Node* b, Label* if_true,
Label* if_false);
void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) { void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) {
BranchIfFloat64Equal(value, value, if_false, if_true); BranchIfFloat64Equal(value, value, if_false, if_true);
} }
protected: // Helpers which delegate to RawMachineAssembler.
// Protected helpers which delegate to RawMachineAssembler.
Graph* graph() const;
Factory* factory() const; Factory* factory() const;
Isolate* isolate() const; Isolate* isolate() const;
Zone* zone() const; Zone* zone() const;
protected:
// Protected helpers which delegate to RawMachineAssembler.
Graph* graph() const;
// Enables subclasses to perform operations before and after a call. // Enables subclasses to perform operations before and after a call.
virtual void CallPrologue(); virtual void CallPrologue();
virtual void CallEpilogue(); virtual void CallEpilogue();
...@@ -323,11 +347,21 @@ DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags); ...@@ -323,11 +347,21 @@ DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
class CodeStubAssembler::Label { class CodeStubAssembler::Label {
public: public:
explicit Label(CodeStubAssembler* assembler); enum Type { kDeferred, kNonDeferred };
Label(CodeStubAssembler* assembler, int merged_variable_count,
CodeStubAssembler::Variable** merged_variables); explicit Label(CodeStubAssembler* assembler,
CodeStubAssembler::Label::Type type =
CodeStubAssembler::Label::kNonDeferred)
: CodeStubAssembler::Label(assembler, 0, nullptr, type) {}
Label(CodeStubAssembler* assembler, Label(CodeStubAssembler* assembler,
CodeStubAssembler::Variable* merged_variable); CodeStubAssembler::Variable* merged_variable,
CodeStubAssembler::Label::Type type =
CodeStubAssembler::Label::kNonDeferred)
: CodeStubAssembler::Label(assembler, 1, &merged_variable, type) {}
Label(CodeStubAssembler* assembler, int merged_variable_count,
CodeStubAssembler::Variable** merged_variables,
CodeStubAssembler::Label::Type type =
CodeStubAssembler::Label::kNonDeferred);
~Label() {} ~Label() {}
private: private:
......
...@@ -89,10 +89,6 @@ REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD) ...@@ -89,10 +89,6 @@ REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
} }
REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual) REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual)
REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual) REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual)
REPLACE_RUNTIME_CALL(JSLessThan, Runtime::kLessThan)
REPLACE_RUNTIME_CALL(JSGreaterThan, Runtime::kGreaterThan)
REPLACE_RUNTIME_CALL(JSLessThanOrEqual, Runtime::kLessThanOrEqual)
REPLACE_RUNTIME_CALL(JSGreaterThanOrEqual, Runtime::kGreaterThanOrEqual)
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext) REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext) REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver) REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
...@@ -104,6 +100,10 @@ REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver) ...@@ -104,6 +100,10 @@ REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
Callable callable = CodeFactory::Name(isolate()); \ Callable callable = CodeFactory::Name(isolate()); \
ReplaceWithStubCall(node, callable, flags); \ ReplaceWithStubCall(node, callable, flags); \
} }
REPLACE_STUB_CALL(LessThan)
REPLACE_STUB_CALL(LessThanOrEqual)
REPLACE_STUB_CALL(GreaterThan)
REPLACE_STUB_CALL(GreaterThanOrEqual)
REPLACE_STUB_CALL(StrictEqual) REPLACE_STUB_CALL(StrictEqual)
REPLACE_STUB_CALL(StrictNotEqual) REPLACE_STUB_CALL(StrictNotEqual)
#undef REPLACE_STUB_CALL #undef REPLACE_STUB_CALL
......
...@@ -428,6 +428,7 @@ void RawMachineAssembler::Bind(RawMachineLabel* label) { ...@@ -428,6 +428,7 @@ void RawMachineAssembler::Bind(RawMachineLabel* label) {
DCHECK(!label->bound_); DCHECK(!label->bound_);
label->bound_ = true; label->bound_ = true;
current_block_ = EnsureBlock(label); current_block_ = EnsureBlock(label);
current_block_->set_deferred(label->deferred_);
} }
...@@ -480,11 +481,6 @@ Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count, ...@@ -480,11 +481,6 @@ Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
return graph()->NewNodeUnchecked(op, input_count, inputs); return graph()->NewNodeUnchecked(op, input_count, inputs);
} }
RawMachineLabel::RawMachineLabel()
: block_(nullptr), used_(false), bound_(false) {}
RawMachineLabel::~RawMachineLabel() { DCHECK(bound_ || !used_); } RawMachineLabel::~RawMachineLabel() { DCHECK(bound_ || !used_); }
} // namespace compiler } // namespace compiler
......
...@@ -700,13 +700,17 @@ class RawMachineAssembler { ...@@ -700,13 +700,17 @@ class RawMachineAssembler {
class RawMachineLabel final { class RawMachineLabel final {
public: public:
RawMachineLabel(); enum Type { kDeferred, kNonDeferred };
explicit RawMachineLabel(Type type = kNonDeferred)
: deferred_(type == kDeferred) {}
~RawMachineLabel(); ~RawMachineLabel();
private: private:
BasicBlock* block_; BasicBlock* block_ = nullptr;
bool used_; bool used_ = false;
bool bound_; bool bound_ = false;
bool deferred_;
friend class RawMachineAssembler; friend class RawMachineAssembler;
DISALLOW_COPY_AND_ASSIGN(RawMachineLabel); DISALLOW_COPY_AND_ASSIGN(RawMachineLabel);
}; };
......
...@@ -1205,7 +1205,7 @@ void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) { ...@@ -1205,7 +1205,7 @@ void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) {
// //
// Test if the value in the <src> register is less than the accumulator. // Test if the value in the <src> register is less than the accumulator.
void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) { void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kLessThan, assembler); DoBinaryOp(CodeFactory::LessThan(isolate_), assembler);
} }
...@@ -1213,7 +1213,7 @@ void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) { ...@@ -1213,7 +1213,7 @@ void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
// //
// Test if the value in the <src> register is greater than the accumulator. // Test if the value in the <src> register is greater than the accumulator.
void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) { void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kGreaterThan, assembler); DoBinaryOp(CodeFactory::GreaterThan(isolate_), assembler);
} }
...@@ -1222,7 +1222,7 @@ void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) { ...@@ -1222,7 +1222,7 @@ void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
// Test if the value in the <src> register is less than or equal to the // Test if the value in the <src> register is less than or equal to the
// accumulator. // accumulator.
void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) { void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kLessThanOrEqual, assembler); DoBinaryOp(CodeFactory::LessThanOrEqual(isolate_), assembler);
} }
...@@ -1231,7 +1231,7 @@ void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) { ...@@ -1231,7 +1231,7 @@ void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
// Test if the value in the <src> register is greater than or equal to the // Test if the value in the <src> register is greater than or equal to the
// accumulator. // accumulator.
void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) { void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kGreaterThanOrEqual, assembler); DoBinaryOp(CodeFactory::GreaterThanOrEqual(isolate_), assembler);
} }
......
...@@ -1145,6 +1145,78 @@ RUNTIME_FUNCTION(Runtime_NewString) { ...@@ -1145,6 +1145,78 @@ RUNTIME_FUNCTION(Runtime_NewString) {
return *result; return *result;
} }
RUNTIME_FUNCTION(Runtime_StringLessThan) {
HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
switch (String::Compare(x, y)) {
case ComparisonResult::kLessThan:
return isolate->heap()->true_value();
case ComparisonResult::kEqual:
case ComparisonResult::kGreaterThan:
return isolate->heap()->false_value();
case ComparisonResult::kUndefined:
break;
}
UNREACHABLE();
return Smi::FromInt(0);
}
RUNTIME_FUNCTION(Runtime_StringLessThanOrEqual) {
HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
switch (String::Compare(x, y)) {
case ComparisonResult::kEqual:
case ComparisonResult::kLessThan:
return isolate->heap()->true_value();
case ComparisonResult::kGreaterThan:
return isolate->heap()->false_value();
case ComparisonResult::kUndefined:
break;
}
UNREACHABLE();
return Smi::FromInt(0);
}
RUNTIME_FUNCTION(Runtime_StringGreaterThan) {
HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
switch (String::Compare(x, y)) {
case ComparisonResult::kGreaterThan:
return isolate->heap()->true_value();
case ComparisonResult::kEqual:
case ComparisonResult::kLessThan:
return isolate->heap()->false_value();
case ComparisonResult::kUndefined:
break;
}
UNREACHABLE();
return Smi::FromInt(0);
}
RUNTIME_FUNCTION(Runtime_StringGreaterThanOrEqual) {
HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
switch (String::Compare(x, y)) {
case ComparisonResult::kEqual:
case ComparisonResult::kGreaterThan:
return isolate->heap()->true_value();
case ComparisonResult::kLessThan:
return isolate->heap()->false_value();
case ComparisonResult::kUndefined:
break;
}
UNREACHABLE();
return Smi::FromInt(0);
}
RUNTIME_FUNCTION(Runtime_StringEqual) { RUNTIME_FUNCTION(Runtime_StringEqual) {
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
......
...@@ -862,6 +862,10 @@ namespace internal { ...@@ -862,6 +862,10 @@ namespace internal {
F(StringTrim, 3, 1) \ F(StringTrim, 3, 1) \
F(TruncateString, 2, 1) \ F(TruncateString, 2, 1) \
F(NewString, 2, 1) \ F(NewString, 2, 1) \
F(StringLessThan, 2, 1) \
F(StringLessThanOrEqual, 2, 1) \
F(StringGreaterThan, 2, 1) \
F(StringGreaterThanOrEqual, 2, 1) \
F(StringEqual, 2, 1) \ F(StringEqual, 2, 1) \
F(StringNotEqual, 2, 1) \ F(StringNotEqual, 2, 1) \
F(FlattenString, 1, 1) \ F(FlattenString, 1, 1) \
......
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