mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
VM-codegen: Clean up the way we emit code for comparison instructions.
Removes some redundancy in the Emit* methods in intermediate_language_*.cc for the 6 architectures we support. This is a reapplication of https://codereview.chromium.org/2937933002/ - see the comments there. It fixes a bug in the way the TestCids instruction was emitted on DBC. R=vegorov@google.com BUG= Review-Url: https://codereview.chromium.org/2947633002 .
This commit is contained in:
parent
9d495064f7
commit
dfb67ecbf8
16 changed files with 333 additions and 902 deletions
|
@ -162,10 +162,20 @@ class Condition : public ValueObject {
|
|||
: public BitField<uword, RelationOperator, kRelOpPos, kRelOpSize> {};
|
||||
class ImmBits : public BitField<uword, uint16_t, kImmPos, kImmSize> {};
|
||||
|
||||
Register left() const { return LeftBits::decode(bits_); }
|
||||
Register right() const { return RightBits::decode(bits_); }
|
||||
Register left() const {
|
||||
ASSERT(IsValid());
|
||||
return LeftBits::decode(bits_);
|
||||
}
|
||||
|
||||
Register right() const {
|
||||
ASSERT(IsValid());
|
||||
return RightBits::decode(bits_);
|
||||
}
|
||||
RelationOperator rel_op() const { return RelOpBits::decode(bits_); }
|
||||
int16_t imm() const { return static_cast<int16_t>(ImmBits::decode(bits_)); }
|
||||
int16_t imm() const {
|
||||
ASSERT(IsValid());
|
||||
return static_cast<int16_t>(ImmBits::decode(bits_));
|
||||
}
|
||||
|
||||
static bool IsValidImm(int32_t value) {
|
||||
// We want both value and value + 1 to fit in an int16_t.
|
||||
|
@ -177,8 +187,10 @@ class Condition : public ValueObject {
|
|||
bits_ = RelOpBits::update(value, bits_);
|
||||
}
|
||||
|
||||
bool IsValid() const { return rel_op() != INVALID_RELATION; }
|
||||
|
||||
// Uninitialized condition.
|
||||
Condition() : ValueObject(), bits_(0) {}
|
||||
Condition() : ValueObject(), bits_(RelOpBits::update(INVALID_RELATION, 0)) {}
|
||||
|
||||
// Copy constructor.
|
||||
Condition(const Condition& other) : ValueObject(), bits_(other.bits_) {}
|
||||
|
@ -200,11 +212,19 @@ class Condition : public ValueObject {
|
|||
ASSERT((imm != 0) == ((left == IMM) || (right == IMM)));
|
||||
set_left(left);
|
||||
set_right(right);
|
||||
set_rel_op(rel_op);
|
||||
if (rel_op == INVALID_RELATION) {
|
||||
SetToInvalidState();
|
||||
} else {
|
||||
set_rel_op(rel_op);
|
||||
}
|
||||
set_imm(imm);
|
||||
}
|
||||
|
||||
private:
|
||||
void SetToInvalidState() {
|
||||
bits_ = RelOpBits::update(INVALID_RELATION, bits_);
|
||||
}
|
||||
|
||||
static bool IsValidRelOp(RelationOperator value) {
|
||||
return (AL <= value) && (value <= ULE);
|
||||
}
|
||||
|
|
|
@ -354,7 +354,8 @@ enum Condition {
|
|||
LE = 13, // signed less than or equal
|
||||
AL = 14, // always (unconditional)
|
||||
kSpecialCondition = 15, // special condition (refer to section A3.2.1)
|
||||
kMaxCondition = 16,
|
||||
kNumberOfConditions = 16,
|
||||
kInvalidCondition = 16
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -193,7 +193,8 @@ enum Condition {
|
|||
LE = 13, // signed less than or equal
|
||||
AL = 14, // always (unconditional)
|
||||
NV = 15, // special condition (refer to section C1.2.3)
|
||||
kMaxCondition = 16,
|
||||
kNumberOfConditions = 16,
|
||||
kInvalidCondition = 16
|
||||
};
|
||||
|
||||
static inline Condition InvertCondition(Condition c) {
|
||||
|
|
|
@ -996,7 +996,7 @@ const intptr_t kNumberOfFpuRegisters = 1;
|
|||
// instruction is executed if the comparison is true and skipped over overwise.
|
||||
// Condition NEXT_IS_FALSE means the following instruction is executed if the
|
||||
// comparison is false and skipped over otherwise.
|
||||
enum Condition { NEXT_IS_TRUE, NEXT_IS_FALSE };
|
||||
enum Condition { NEXT_IS_TRUE, NEXT_IS_FALSE, INVALID_CONDITION };
|
||||
|
||||
} // namespace dart
|
||||
|
||||
|
|
|
@ -122,7 +122,9 @@ enum Condition {
|
|||
NEGATIVE = SIGN,
|
||||
POSITIVE = NOT_SIGN,
|
||||
CARRY = BELOW,
|
||||
NOT_CARRY = ABOVE_EQUAL
|
||||
NOT_CARRY = ABOVE_EQUAL,
|
||||
|
||||
INVALID_CONDITION = 16
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ enum RelationOperator {
|
|||
UGE, // unsigned greater equal
|
||||
ULT, // unsigned less than
|
||||
ULE, // unsigned less equal
|
||||
INVALID_RELATION
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -147,7 +147,9 @@ enum Condition {
|
|||
NEGATIVE = SIGN,
|
||||
POSITIVE = NOT_SIGN,
|
||||
CARRY = BELOW,
|
||||
NOT_CARRY = ABOVE_EQUAL
|
||||
NOT_CARRY = ABOVE_EQUAL,
|
||||
|
||||
INVALID_CONDITION = 16
|
||||
};
|
||||
|
||||
#define R(reg) (1 << (reg))
|
||||
|
|
|
@ -96,7 +96,7 @@ void ARMDecoder::Print(const char* str) {
|
|||
|
||||
// These condition names are defined in a way to match the native disassembler
|
||||
// formatting. See for example the command "objdump -d <binary file>".
|
||||
static const char* cond_names[kMaxCondition] = {
|
||||
static const char* cond_names[kNumberOfConditions] = {
|
||||
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
|
||||
"hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
|
||||
};
|
||||
|
|
|
@ -125,7 +125,7 @@ static const char* extend_names[kMaxExtend] = {
|
|||
|
||||
// These condition names are defined in a way to match the native disassembler
|
||||
// formatting. See for example the command "objdump -d <binary file>".
|
||||
static const char* cond_names[kMaxCondition] = {
|
||||
static const char* cond_names[kNumberOfConditions] = {
|
||||
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
|
||||
"hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
|
||||
};
|
||||
|
|
|
@ -536,6 +536,26 @@ FOR_EACH_ABSTRACT_INSTRUCTION(FORWARD_DECLARATION)
|
|||
DECLARE_INSTRUCTION_NO_BACKEND(type) \
|
||||
DECLARE_INSTRUCTION_BACKEND()
|
||||
|
||||
#if defined(TARGET_ARCH_DBC)
|
||||
#define DECLARE_COMPARISON_METHODS \
|
||||
virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing) \
|
||||
const; \
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, \
|
||||
BranchLabels labels); \
|
||||
virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler, \
|
||||
BranchLabels labels);
|
||||
#else
|
||||
#define DECLARE_COMPARISON_METHODS \
|
||||
virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing) \
|
||||
const; \
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, \
|
||||
BranchLabels labels);
|
||||
#endif
|
||||
|
||||
#define DECLARE_COMPARISON_INSTRUCTION(type) \
|
||||
DECLARE_INSTRUCTION_NO_BACKEND(type) \
|
||||
DECLARE_COMPARISON_METHODS
|
||||
|
||||
#ifndef PRODUCT
|
||||
#define PRINT_TO_SUPPORT virtual void PrintTo(BufferFormatter* f) const;
|
||||
#else
|
||||
|
@ -966,6 +986,13 @@ class Instruction : public ZoneAllocated {
|
|||
};
|
||||
|
||||
|
||||
struct BranchLabels {
|
||||
Label* true_label;
|
||||
Label* false_label;
|
||||
Label* fall_through;
|
||||
};
|
||||
|
||||
|
||||
class PureInstruction : public Instruction {
|
||||
public:
|
||||
explicit PureInstruction(intptr_t deopt_id) : Instruction(deopt_id) {}
|
||||
|
@ -1920,13 +1947,6 @@ class TemplateDefinition : public CSETrait<Definition, PureDefinition>::Base {
|
|||
};
|
||||
|
||||
|
||||
struct BranchLabels {
|
||||
Label* true_label;
|
||||
Label* false_label;
|
||||
Label* fall_through;
|
||||
};
|
||||
|
||||
|
||||
class InductionVariableInfo;
|
||||
|
||||
|
||||
|
@ -2345,12 +2365,34 @@ class ComparisonInstr : public Definition {
|
|||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0;
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) = 0;
|
||||
// Emits instructions to do the comparison and branch to the true or false
|
||||
// label depending on the result. This implementation will call
|
||||
// EmitComparisonCode and then generate the branch instructions afterwards.
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
// Used by EmitBranchCode and EmitNativeCode depending on whether the boolean
|
||||
// is to be turned into branches or instantiated. May return a valid
|
||||
// condition in which case the caller is expected to emit a branch to the
|
||||
// true label based on that condition (or a branch to the false label on the
|
||||
// opposite condition). May also branch directly to the labels.
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) = 0;
|
||||
|
||||
#if defined(TARGET_ARCH_DBC)
|
||||
// On the DBC platform EmitNativeCode needs to know ahead of time what
|
||||
// 'Condition' will be returned by EmitComparisonCode. This call must return
|
||||
// the same result as EmitComparisonCode, but should not emit any
|
||||
// instructions.
|
||||
virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) = 0;
|
||||
#endif
|
||||
|
||||
// Emits code that generates 'true' or 'false', depending on the comparison.
|
||||
// This implementation will call EmitComparisonCode. If EmitComparisonCode
|
||||
// does not use the labels (merely returning a condition) then EmitNativeCode
|
||||
// may be able to use the condition to avoid a branch.
|
||||
virtual void EmitNativeCode(FlowGraphCompiler* compiler);
|
||||
|
||||
void SetDeoptId(const Instruction& instr) { CopyDeoptIdFrom(instr); }
|
||||
|
||||
// Operation class id is computed from collected ICData.
|
||||
|
@ -3038,7 +3080,7 @@ class StrictCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
bool needs_number_check,
|
||||
intptr_t deopt_id);
|
||||
|
||||
DECLARE_INSTRUCTION(StrictCompare)
|
||||
DECLARE_COMPARISON_INSTRUCTION(StrictCompare)
|
||||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
|
@ -3048,11 +3090,6 @@ class StrictCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
|
||||
virtual Definition* Canonicalize(FlowGraph* flow_graph);
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
bool needs_number_check() const { return needs_number_check_; }
|
||||
void set_needs_number_check(bool value) { needs_number_check_ = value; }
|
||||
|
||||
|
@ -3083,7 +3120,7 @@ class TestSmiInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
SetInputAt(1, right);
|
||||
}
|
||||
|
||||
DECLARE_INSTRUCTION(TestSmi);
|
||||
DECLARE_COMPARISON_INSTRUCTION(TestSmi);
|
||||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
|
@ -3095,11 +3132,6 @@ class TestSmiInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
return kTagged;
|
||||
}
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TestSmiInstr);
|
||||
};
|
||||
|
@ -3124,7 +3156,7 @@ class TestCidsInstr : public TemplateComparison<1, NoThrow, Pure> {
|
|||
return cid_results_;
|
||||
}
|
||||
|
||||
DECLARE_INSTRUCTION(TestCids);
|
||||
DECLARE_COMPARISON_INSTRUCTION(TestCids);
|
||||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
|
@ -3142,11 +3174,6 @@ class TestCidsInstr : public TemplateComparison<1, NoThrow, Pure> {
|
|||
|
||||
virtual bool AttributesEqual(Instruction* other) const;
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
void set_licm_hoisted(bool value) { licm_hoisted_ = value; }
|
||||
|
||||
PRINT_OPERANDS_TO_SUPPORT
|
||||
|
@ -3173,7 +3200,7 @@ class EqualityCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
set_operation_cid(cid);
|
||||
}
|
||||
|
||||
DECLARE_INSTRUCTION(EqualityCompare)
|
||||
DECLARE_COMPARISON_INSTRUCTION(EqualityCompare)
|
||||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
|
@ -3181,11 +3208,6 @@ class EqualityCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
|
||||
virtual bool ComputeCanDeoptimize() const { return false; }
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
|
||||
ASSERT((idx == 0) || (idx == 1));
|
||||
if (operation_cid() == kDoubleCid) return kUnboxedDouble;
|
||||
|
@ -3215,7 +3237,7 @@ class RelationalOpInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
set_operation_cid(cid);
|
||||
}
|
||||
|
||||
DECLARE_INSTRUCTION(RelationalOp)
|
||||
DECLARE_COMPARISON_INSTRUCTION(RelationalOp)
|
||||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
|
@ -3223,11 +3245,6 @@ class RelationalOpInstr : public TemplateComparison<2, NoThrow, Pure> {
|
|||
|
||||
virtual bool ComputeCanDeoptimize() const { return false; }
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
|
||||
ASSERT((idx == 0) || (idx == 1));
|
||||
if (operation_cid() == kDoubleCid) return kUnboxedDouble;
|
||||
|
@ -5348,7 +5365,8 @@ class DoubleTestOpInstr : public TemplateComparison<1, NoThrow, Pure> {
|
|||
|
||||
PRINT_OPERANDS_TO_SUPPORT
|
||||
|
||||
DECLARE_INSTRUCTION(DoubleTestOp)
|
||||
DECLARE_COMPARISON_INSTRUCTION(DoubleTestOp)
|
||||
|
||||
virtual CompileType ComputeType() const;
|
||||
|
||||
virtual Definition* Canonicalize(FlowGraph* flow_graph);
|
||||
|
@ -5360,11 +5378,6 @@ class DoubleTestOpInstr : public TemplateComparison<1, NoThrow, Pure> {
|
|||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
|
||||
|
||||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
private:
|
||||
const MethodRecognizer::Kind op_kind_;
|
||||
|
||||
|
@ -6934,6 +6947,14 @@ class CheckedSmiComparisonInstr : public TemplateComparison<2, Throws> {
|
|||
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels);
|
||||
|
||||
#if defined(TARGET_ARCH_DBC)
|
||||
virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
UNREACHABLE();
|
||||
return INVALID_CONDITION;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
|
||||
|
||||
private:
|
||||
|
|
|
@ -169,8 +169,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ eor(result, result, Operand(result));
|
||||
|
||||
// Emit comparison code. This must not overwrite the result register.
|
||||
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
|
||||
// the labels or returning an invalid condition.
|
||||
BranchLabels labels = {NULL, NULL, NULL};
|
||||
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
|
||||
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
|
||||
|
||||
|
@ -666,6 +669,7 @@ static Condition TokenKindToDoubleCondition(Token::Kind kind) {
|
|||
|
||||
static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
|
||||
LocationSummary* locs,
|
||||
BranchLabels labels,
|
||||
Token::Kind kind) {
|
||||
const QRegister left = locs->in(0).fpu_reg();
|
||||
const QRegister right = locs->in(1).fpu_reg();
|
||||
|
@ -674,6 +678,11 @@ static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
|
|||
__ vcmpd(dleft, dright);
|
||||
__ vmstat();
|
||||
Condition true_condition = TokenKindToDoubleCondition(kind);
|
||||
if (true_condition != NE) {
|
||||
// Special case for NaN comparison. Result is always false unless
|
||||
// relational operator is !=.
|
||||
__ b(labels.false_label, VS);
|
||||
}
|
||||
return true_condition;
|
||||
}
|
||||
|
||||
|
@ -686,51 +695,11 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
return EmitUnboxedMintEqualityOp(compiler, locs(), kind());
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
return EmitDoubleComparisonOp(compiler, locs(), kind());
|
||||
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
// The ARM code does not use true- and false-labels here.
|
||||
BranchLabels labels = {NULL, NULL, NULL};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
|
||||
const Register result = locs()->out(0).reg();
|
||||
if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) {
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
Label done;
|
||||
__ LoadObject(result, Bool::False());
|
||||
if (true_condition != NE) {
|
||||
__ b(&done, VS); // x == NaN -> false, x != NaN -> true.
|
||||
}
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ Bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
|
||||
if (operation_cid() == kDoubleCid) {
|
||||
Label* nan_result =
|
||||
(true_condition == NE) ? labels.true_label : labels.false_label;
|
||||
__ b(nan_result, VS);
|
||||
}
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
const intptr_t kNumTemps = 0;
|
||||
|
@ -760,20 +729,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Never emitted outside of the BranchInstr.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
|
@ -826,30 +781,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
} else {
|
||||
__ b(deopt);
|
||||
}
|
||||
// Dummy result as the last instruction is a jump, any conditional
|
||||
// branch using the result will therefore be skipped.
|
||||
return EQ;
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
EmitComparisonCode(compiler, labels);
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register result_reg = locs()->out(0).reg();
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
EmitComparisonCode(compiler, labels);
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result_reg, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result_reg, Bool::True());
|
||||
__ Bind(&done);
|
||||
// Dummy result as this method already did the jump, there's no need
|
||||
// for the caller to branch on a condition.
|
||||
return kInvalidCondition;
|
||||
}
|
||||
|
||||
|
||||
|
@ -898,54 +832,7 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels);
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
return EmitDoubleComparisonOp(compiler, locs(), kind());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
|
||||
const Register result = locs()->out(0).reg();
|
||||
if (operation_cid() == kSmiCid) {
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
|
||||
} else if (operation_cid() == kMintCid) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
Label done;
|
||||
__ LoadObject(result, Bool::False());
|
||||
if (true_condition != NE) {
|
||||
__ b(&done, VS); // x == NaN -> false, x != NaN -> true.
|
||||
}
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ Bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
|
||||
if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
} else if (operation_cid() == kDoubleCid) {
|
||||
Label* nan_result =
|
||||
(true_condition == NE) ? labels.true_label : labels.false_label;
|
||||
__ b(nan_result, VS);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3428,6 +3315,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
@ -3441,6 +3329,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
Register result = locs()->out(0).reg();
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
|
||||
|
@ -4404,38 +4293,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
}
|
||||
|
||||
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
const Register result = locs()->out(0).reg();
|
||||
if (op_kind() == MethodRecognizer::kDouble_getIsNaN) {
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
|
||||
} else {
|
||||
ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
|
@ -7217,26 +7074,40 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
// The ARM code does not use true- and false-labels here.
|
||||
BranchLabels labels = {NULL, NULL, NULL};
|
||||
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// The ARM code may not use true- and false-labels here.
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
|
||||
const Register result = locs()->out(0).reg();
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
|
||||
const Register result = this->locs()->out(0).reg();
|
||||
if (is_false.IsLinked() || is_true.IsLinked()) {
|
||||
if (true_condition != kInvalidCondition) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
} else {
|
||||
// If EmitComparisonCode did not use the labels and just returned
|
||||
// a condition we can avoid the branch and use conditional loads.
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
__ LoadObject(result, Bool::True(), true_condition);
|
||||
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != kInvalidCondition) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -165,8 +165,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
ASSERT(!left.IsConstant() || !right.IsConstant());
|
||||
|
||||
// Emit comparison code. This must not overwrite the result register.
|
||||
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
|
||||
// the labels or returning an invalid condition.
|
||||
BranchLabels labels = {NULL, NULL, NULL};
|
||||
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
|
||||
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
|
||||
|
||||
|
@ -540,11 +543,17 @@ static Condition TokenKindToDoubleCondition(Token::Kind kind) {
|
|||
|
||||
static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
|
||||
LocationSummary* locs,
|
||||
BranchLabels labels,
|
||||
Token::Kind kind) {
|
||||
const VRegister left = locs->in(0).fpu_reg();
|
||||
const VRegister right = locs->in(1).fpu_reg();
|
||||
__ fcmpd(left, right);
|
||||
Condition true_condition = TokenKindToDoubleCondition(kind);
|
||||
if (true_condition != NE) {
|
||||
// Special case for NaN comparison. Result is always false unless
|
||||
// relational operator is !=.
|
||||
__ b(labels.false_label, VS);
|
||||
}
|
||||
return true_condition;
|
||||
}
|
||||
|
||||
|
@ -555,50 +564,11 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
return EmitSmiComparisonOp(compiler, locs(), kind());
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
return EmitDoubleComparisonOp(compiler, locs(), kind());
|
||||
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
|
||||
// Special case for NaN comparison. Result is always false unless
|
||||
// relational operator is !=.
|
||||
__ b(&is_false, VS);
|
||||
}
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
// TODO(zra): instead of branching, use the csel instruction to get
|
||||
// True or False into result.
|
||||
const Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
|
||||
// Special case for NaN comparison. Result is always false unless
|
||||
// relational operator is !=.
|
||||
__ b(labels.false_label, VS);
|
||||
}
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
const intptr_t kNumTemps = 0;
|
||||
|
@ -628,20 +598,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Never emitted outside of the BranchInstr.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
|
@ -694,32 +650,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
} else {
|
||||
__ b(deopt);
|
||||
}
|
||||
// Dummy result as the last instruction is a jump, any conditional
|
||||
// branch using the result will therefore be skipped.
|
||||
return EQ;
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
EmitComparisonCode(compiler, labels);
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register result_reg = locs()->out(0).reg();
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
EmitComparisonCode(compiler, labels);
|
||||
// TODO(zra): instead of branching, use the csel instruction to get
|
||||
// True or False into result.
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result_reg, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result_reg, Bool::True());
|
||||
__ Bind(&done);
|
||||
// Dummy result as this method already did the jump, there's no need
|
||||
// for the caller to branch on a condition.
|
||||
return kInvalidCondition;
|
||||
}
|
||||
|
||||
|
||||
|
@ -755,47 +688,11 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
return EmitSmiComparisonOp(compiler, locs(), kind());
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
return EmitDoubleComparisonOp(compiler, locs(), kind());
|
||||
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
|
||||
// Special case for NaN comparison. Result is always false unless
|
||||
// relational operator is !=.
|
||||
__ b(&is_false, VS);
|
||||
}
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
// TODO(zra): instead of branching, use the csel instruction to get
|
||||
// True or False into result.
|
||||
const Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
|
||||
// Special case for NaN comparison. Result is always false unless
|
||||
// relational operator is !=.
|
||||
__ b(labels.false_label, VS);
|
||||
}
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return MakeCallSummary(zone);
|
||||
|
@ -3136,6 +3033,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
@ -3150,6 +3048,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != kInvalidCondition);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Register result = locs()->out(0).reg();
|
||||
__ Bind(&false_label);
|
||||
|
@ -3778,33 +3677,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
const Register result = locs()->out(0).reg();
|
||||
if (op_kind() == MethodRecognizer::kDouble_getIsNaN) {
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ LoadObject(TMP, Bool::True());
|
||||
__ csel(result, TMP, result, true_condition);
|
||||
} else {
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ LoadObject(TMP, Bool::True());
|
||||
__ csel(result, TMP, result, true_condition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
|
@ -6008,16 +5880,16 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("StrictCompareInstr");
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
const Register result = this->locs()->out(0).reg();
|
||||
|
||||
const Register result = locs()->out(0).reg();
|
||||
// TODO(dartbug.com/29908): Use csel here for better branch prediction?
|
||||
if (true_condition != kInvalidCondition) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
|
@ -6028,13 +5900,13 @@ void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != kInvalidCondition) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -483,6 +483,14 @@ static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
Condition StrictCompareInstr::GetNextInstructionCondition(
|
||||
FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE
|
||||
: NEXT_IS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT));
|
||||
|
@ -526,43 +534,68 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT));
|
||||
DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare,
|
||||
2,
|
||||
Location::RequiresRegister(),
|
||||
needs_number_check() ? LocationSummary::kCall
|
||||
: LocationSummary::kNoCall)
|
||||
|
||||
|
||||
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != INVALID_CONDITION) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(StrictCompare,
|
||||
2,
|
||||
Location::RequiresRegister(),
|
||||
needs_number_check() ? LocationSummary::kCall
|
||||
: LocationSummary::kNoCall) {
|
||||
ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT));
|
||||
|
||||
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Label done;
|
||||
if (compiler->is_optimizing()) {
|
||||
const Register result = locs()->out(0).reg();
|
||||
__ Bind(&is_false);
|
||||
__ LoadConstant(result, Bool::False());
|
||||
__ Jump(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadConstant(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
} else {
|
||||
Condition true_condition =
|
||||
this->GetNextInstructionCondition(compiler, labels);
|
||||
if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() ||
|
||||
is_true.IsLinked() || is_false.IsLinked()) {
|
||||
Condition actual_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(actual_condition == true_condition);
|
||||
if (true_condition != INVALID_CONDITION) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ PushConstant(Bool::False());
|
||||
__ Jump(&done);
|
||||
__ Bind(&is_true);
|
||||
__ PushConstant(Bool::True());
|
||||
__ Bind(&done);
|
||||
} else {
|
||||
const Register result = this->locs()->out(0).reg();
|
||||
bool next_is_true = true_condition == NEXT_IS_TRUE;
|
||||
__ LoadConstant(result, Bool::Get(!next_is_true));
|
||||
Condition actual_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(actual_condition == true_condition);
|
||||
// Although we have a condition to branch on, the comparison code may also
|
||||
// have contained a direct branch to one of the labels, so they may need to
|
||||
// be bound.
|
||||
if (next_is_true && is_true.IsLinked()) {
|
||||
__ Bind(&is_true);
|
||||
} else if (!next_is_true && is_false.IsLinked()) {
|
||||
__ Bind(&is_false);
|
||||
}
|
||||
// This instruction is conditionally skipped by EmitComparisonCode.
|
||||
__ LoadConstant(result, Bool::Get(next_is_true));
|
||||
// If the other label is linked we need to bind it and emit code that loads
|
||||
// the correct boolean.
|
||||
if ((next_is_true && is_false.IsLinked()) ||
|
||||
(!next_is_true && is_true.IsLinked())) {
|
||||
Label done;
|
||||
__ Jump(&done);
|
||||
__ Bind(next_is_true ? &is_false : &is_true);
|
||||
__ LoadConstant(result, Bool::Get(!next_is_true));
|
||||
__ Bind(&done);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,6 +634,13 @@ EMIT_NATIVE_CODE(Goto, 0) {
|
|||
}
|
||||
|
||||
|
||||
Condition TestSmiInstr::GetNextInstructionCondition(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
|
||||
return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
|
||||
|
@ -611,21 +651,10 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(TestSmi,
|
||||
2,
|
||||
Location::RequiresRegister(),
|
||||
LocationSummary::kNoCall) {
|
||||
// Never emitted outside of the BranchInstr.
|
||||
UNREACHABLE();
|
||||
}
|
||||
DEFINE_MAKE_LOCATION_SUMMARY(TestSmi,
|
||||
2,
|
||||
Location::RequiresRegister(),
|
||||
LocationSummary::kNoCall)
|
||||
|
||||
|
||||
Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
|
@ -662,30 +691,17 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Condition TestCidsInstr::GetNextInstructionCondition(
|
||||
FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
return NEXT_IS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(TestCids,
|
||||
1,
|
||||
Location::RequiresRegister(),
|
||||
LocationSummary::kNoCall) {
|
||||
Register result_reg = locs()->out(0).reg();
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
EmitComparisonCode(compiler, labels);
|
||||
__ Jump(&is_true);
|
||||
__ Bind(&is_false);
|
||||
__ LoadConstant(result_reg, Bool::False());
|
||||
__ Jump(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadConstant(result_reg, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
DEFINE_MAKE_LOCATION_SUMMARY(TestCids,
|
||||
1,
|
||||
Location::RequiresRegister(),
|
||||
LocationSummary::kNoCall)
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(CreateArray,
|
||||
|
@ -1753,15 +1769,7 @@ EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) {
|
|||
|
||||
Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
UNREACHABLE();
|
||||
return Condition();
|
||||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
const Register value = locs()->in(0).reg();
|
||||
switch (op_kind()) {
|
||||
case MethodRecognizer::kDouble_getIsNaN:
|
||||
|
@ -1774,31 +1782,21 @@ void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
|||
UNREACHABLE();
|
||||
}
|
||||
const bool is_negated = kind() != Token::kEQ;
|
||||
EmitBranchOnCondition(compiler, is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE,
|
||||
labels);
|
||||
return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(DoubleTestOp, 1, Location::RequiresRegister()) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
const Register value = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
Condition DoubleTestOpInstr::GetNextInstructionCondition(
|
||||
FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
const bool is_negated = kind() != Token::kEQ;
|
||||
__ LoadConstant(result, is_negated ? Bool::True() : Bool::False());
|
||||
switch (op_kind()) {
|
||||
case MethodRecognizer::kDouble_getIsNaN:
|
||||
__ DoubleIsNaN(value);
|
||||
break;
|
||||
case MethodRecognizer::kDouble_getIsInfinite:
|
||||
__ DoubleIsInfinite(value);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
__ LoadConstant(result, is_negated ? Bool::False() : Bool::True());
|
||||
return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister())
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) {
|
||||
const Register value = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
|
@ -1973,7 +1971,8 @@ static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
|
|||
// If we aren't falling through to the false label, we can save a Jump
|
||||
// instruction in the case that the true case is the fall through by
|
||||
// flipping the sense of the test such that the instruction following the
|
||||
// test is the Jump to the false label.
|
||||
// test is the Jump to the false label. In the case where both labels are
|
||||
// null we don't flip the sense of the test.
|
||||
condition = NEXT_IS_FALSE;
|
||||
comparison = FlipCondition(kind);
|
||||
}
|
||||
|
@ -2010,29 +2009,20 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
|
||||
Label is_true, is_false;
|
||||
// These labels are not used. They are arranged so that EmitComparisonCode
|
||||
// emits a test that executes the following instruction when the test
|
||||
// succeeds.
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
const Register result = locs()->out(0).reg();
|
||||
__ LoadConstant(result, Bool::False());
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition == NEXT_IS_TRUE);
|
||||
__ LoadConstant(result, Bool::True());
|
||||
Condition EqualityCompareInstr::GetNextInstructionCondition(
|
||||
FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
if (operation_cid() == kSmiCid) {
|
||||
return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
|
||||
: NEXT_IS_TRUE;
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
return NEXT_IS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister());
|
||||
|
||||
|
||||
Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
|
@ -2046,24 +2036,20 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
const Register result = locs()->out(0).reg();
|
||||
__ LoadConstant(result, Bool::False());
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition == NEXT_IS_TRUE);
|
||||
__ LoadConstant(result, Bool::True());
|
||||
Condition RelationalOpInstr::GetNextInstructionCondition(
|
||||
FlowGraphCompiler* compiler,
|
||||
BranchLabels labels) {
|
||||
if (operation_cid() == kSmiCid) {
|
||||
return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
|
||||
: NEXT_IS_TRUE;
|
||||
} else {
|
||||
ASSERT(operation_cid() == kDoubleCid);
|
||||
return NEXT_IS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister())
|
||||
|
||||
|
||||
EMIT_NATIVE_CODE(CheckArrayBound, 2) {
|
||||
|
|
|
@ -600,13 +600,13 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != INVALID_CONDITION) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
|
@ -619,13 +619,13 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != INVALID_CONDITION) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -658,20 +658,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Never emitted outside of the BranchInstr.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
|
@ -723,30 +709,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
} else {
|
||||
__ jmp(deopt);
|
||||
}
|
||||
// Dummy result as the last instruction is a jump, any conditional
|
||||
// branch using the result will therefore be skipped.
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
EmitComparisonCode(compiler, labels);
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result_reg = locs()->out(0).reg();
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
EmitComparisonCode(compiler, labels);
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result_reg, Bool::False());
|
||||
__ jmp(&done, Assembler::kNearJump);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result_reg, Bool::True());
|
||||
__ Bind(&done);
|
||||
// Dummy result as this method already did the jump, there's no need
|
||||
// for the caller to branch on a condition.
|
||||
return INVALID_CONDITION;
|
||||
}
|
||||
|
||||
|
||||
|
@ -800,31 +765,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ jmp(&done, Assembler::kNearJump);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return MakeCallSummary(zone);
|
||||
|
@ -3995,32 +3935,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ jmp(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
|
@ -6717,35 +6631,6 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ jmp(&done, Assembler::kNearJump);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
// Detect pattern when one value is zero and another is a power of 2.
|
||||
static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
|
||||
return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
|
||||
|
@ -6770,8 +6655,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ xorl(EDX, EDX);
|
||||
|
||||
// Emit comparison code. This must not overwrite the result register.
|
||||
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
|
||||
// the labels or returning an invalid condition.
|
||||
BranchLabels labels = {NULL, NULL, NULL};
|
||||
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != INVALID_CONDITION);
|
||||
|
||||
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
|
||||
|
||||
|
|
|
@ -178,8 +178,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ LoadImmediate(result, Smi::RawValue(true_value));
|
||||
|
||||
// Emit comparison code. This must not overwrite the result register.
|
||||
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
|
||||
// the labels or returning an invalid condition.
|
||||
BranchLabels labels = {NULL, NULL, NULL}; // Emit branch-free code.
|
||||
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition.IsValid());
|
||||
if (swapped) {
|
||||
true_condition = NegateCondition(true_condition);
|
||||
}
|
||||
|
@ -781,16 +784,15 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
__ Comment("EqualityCompareInstr");
|
||||
|
||||
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition.IsValid()) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Register result = this->locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
|
@ -801,14 +803,13 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
__ Comment("EqualityCompareInstr::EmitBranchCode");
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition.IsValid()) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -840,20 +841,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Never emitted outside of the BranchInstr.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
|
@ -906,29 +893,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
} else {
|
||||
__ b(deopt);
|
||||
}
|
||||
// Dummy result as the last instruction is a jump or fall through.
|
||||
return Condition(CMPRES1, ZR, AL);
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
EmitComparisonCode(compiler, labels);
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result_reg = locs()->out(0).reg();
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
EmitComparisonCode(compiler, labels);
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result_reg, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result_reg, Bool::True());
|
||||
__ Bind(&done);
|
||||
// Dummy result as this method already did the jump, there's no need
|
||||
// for the caller to branch on a condition.
|
||||
return Condition(ZR, ZR, INVALID_RELATION);
|
||||
}
|
||||
|
||||
|
||||
|
@ -982,35 +949,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("RelationalOpInstr");
|
||||
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
__ Comment("RelationalOpInstr");
|
||||
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return MakeCallSummary(zone);
|
||||
|
@ -3247,6 +3185,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition.IsValid());
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
@ -3261,6 +3200,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition.IsValid());
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Register result = locs()->out(0).reg();
|
||||
__ Bind(&false_label);
|
||||
|
@ -3975,7 +3915,7 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
__ b(labels.true_label);
|
||||
}
|
||||
return Condition(); // Unused.
|
||||
return Condition(ZR, ZR, INVALID_RELATION); // Unused.
|
||||
} else {
|
||||
ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite);
|
||||
__ mfc1(CMPRES1, EvenFRegisterOf(value));
|
||||
|
@ -3990,38 +3930,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
}
|
||||
|
||||
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
// Branches for isNaN are emitted in EmitComparisonCode already.
|
||||
if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
// Branches for isNaN are emitted in EmitComparisonCode already.
|
||||
if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
const Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Comment("return bool");
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
UNIMPLEMENTED();
|
||||
|
@ -5986,37 +5894,6 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ Comment("StrictCompareInstr");
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ b(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
__ Comment("StrictCompareInstr::EmitBranchCode");
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
|
||||
|
|
|
@ -165,8 +165,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ xorq(RDX, RDX);
|
||||
|
||||
// Emit comparison code. This must not overwrite the result register.
|
||||
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
|
||||
// the labels or returning an invalid condition.
|
||||
BranchLabels labels = {NULL, NULL, NULL};
|
||||
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != INVALID_CONDITION);
|
||||
|
||||
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
|
||||
|
||||
|
@ -573,13 +576,13 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
|
||||
|
||||
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != INVALID_CONDITION) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
|
@ -592,13 +595,13 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
|
||||
|
||||
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
|
||||
|
||||
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
if (true_condition != INVALID_CONDITION) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -631,20 +634,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Never emitted outside of the BranchInstr.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
|
@ -696,30 +685,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
} else {
|
||||
__ jmp(deopt);
|
||||
}
|
||||
// Dummy result as the last instruction is a jump, any conditional
|
||||
// branch using the result will therefore be skipped.
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
EmitComparisonCode(compiler, labels);
|
||||
}
|
||||
|
||||
|
||||
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result_reg = locs()->out(0).reg();
|
||||
Label is_true, is_false, done;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
EmitComparisonCode(compiler, labels);
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result_reg, Bool::False());
|
||||
__ jmp(&done, Assembler::kNearJump);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result_reg, Bool::True());
|
||||
__ Bind(&done);
|
||||
// Dummy result as this method already did the jump, there's no need
|
||||
// for the caller to branch on a condition.
|
||||
return INVALID_CONDITION;
|
||||
}
|
||||
|
||||
|
||||
|
@ -767,31 +735,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ jmp(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return MakeCallSummary(zone);
|
||||
|
@ -3109,6 +3052,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != INVALID_CONDITION);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
__ Bind(slow_path->exit_label());
|
||||
}
|
||||
|
@ -3123,6 +3067,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->AddSlowPathCode(slow_path);
|
||||
EMIT_SMI_CHECK;
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
ASSERT(true_condition != INVALID_CONDITION);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
Register result = locs()->out(0).reg();
|
||||
__ Bind(&false_label);
|
||||
|
@ -3951,32 +3896,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(compiler->is_optimizing());
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ jmp(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
|
@ -6638,36 +6557,6 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
|||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
Label is_true, is_false;
|
||||
BranchLabels labels = {&is_true, &is_false, &is_false};
|
||||
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
Label done;
|
||||
__ Bind(&is_false);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ jmp(&done);
|
||||
__ Bind(&is_true);
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
|
||||
BranchInstr* branch) {
|
||||
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
|
||||
|
||||
BranchLabels labels = compiler->CreateBranchLabels(branch);
|
||||
Condition true_condition = EmitComparisonCode(compiler, labels);
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
|
||||
LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
|
|
Loading…
Reference in a new issue