Make the CompareStub and the UnaryOpStub accept smi inputs.

The stubs get an additional flag for including the smi code
inside the stub. This allows us to generate more compact code
if we don't want to inline the smi case outside the stub.

Review URL: http://codereview.chromium.org/3388005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5456 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2010-09-15 10:14:25 +00:00
parent dae5fc6f81
commit bd6a8c1e4e
14 changed files with 393 additions and 152 deletions

View File

@ -930,6 +930,24 @@ void CompareStub::Generate(MacroAssembler* masm) {
Label slow; // Call builtin. Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles, lhs_not_nan; Label not_smis, both_loaded_as_doubles, lhs_not_nan;
if (include_smi_compare_) {
Label not_two_smis, smi_done;
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &not_two_smis);
__ sub(r0, r1, r0);
__ b(vc, &smi_done);
// Correct the sign in case of overflow.
__ rsb(r0, r0, Operand(0, RelocInfo::NONE));
__ bind(&smi_done);
__ Ret();
__ bind(&not_two_smis);
} else if (FLAG_debug_code) {
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ Assert(nz, "CompareStub: unexpected smi operands.");
}
// NOTICE! This code is only reached after a smi-fast-case check, so // NOTICE! This code is only reached after a smi-fast-case check, so
// it is certain that at least one operand isn't a smi. // it is certain that at least one operand isn't a smi.
@ -2288,7 +2306,7 @@ void StackCheckStub::Generate(MacroAssembler* masm) {
__ push(r0); __ push(r0);
__ TailCallRuntime(Runtime::kStackGuard, 1, 1); __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
__ StubReturn(1); __ Ret();
} }
@ -2299,32 +2317,37 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
if (op_ == Token::SUB) { if (op_ == Token::SUB) {
// Check whether the value is a smi. if (include_smi_code_) {
Label try_float; // Check whether the value is a smi.
__ tst(r0, Operand(kSmiTagMask)); Label try_float;
__ b(ne, &try_float); __ tst(r0, Operand(kSmiTagMask));
__ b(ne, &try_float);
// Go slow case if the value of the expression is zero // Go slow case if the value of the expression is zero
// to make sure that we switch between 0 and -0. // to make sure that we switch between 0 and -0.
if (negative_zero_ == kStrictNegativeZero) { if (negative_zero_ == kStrictNegativeZero) {
// If we have to check for zero, then we can check for the max negative // If we have to check for zero, then we can check for the max negative
// smi while we are at it. // smi while we are at it.
__ bic(ip, r0, Operand(0x80000000), SetCC); __ bic(ip, r0, Operand(0x80000000), SetCC);
__ b(eq, &slow); __ b(eq, &slow);
__ rsb(r0, r0, Operand(0, RelocInfo::NONE)); __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
__ StubReturn(1); __ Ret();
} else { } else {
// The value of the expression is a smi and 0 is OK for -0. Try // The value of the expression is a smi and 0 is OK for -0. Try
// optimistic subtraction '0 - value'. // optimistic subtraction '0 - value'.
__ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC); __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
__ StubReturn(1, vc); __ Ret(vc);
// We don't have to reverse the optimistic neg since the only case // We don't have to reverse the optimistic neg since the only case
// where we fall through is the minimum negative Smi, which is the case // where we fall through is the minimum negative Smi, which is the case
// where the neg leaves the register unchanged. // where the neg leaves the register unchanged.
__ jmp(&slow); // Go slow on max negative Smi. __ jmp(&slow); // Go slow on max negative Smi.
}
__ bind(&try_float);
} else if (FLAG_debug_code) {
__ tst(r0, Operand(kSmiTagMask));
__ Assert(ne, "Unexpected smi operand.");
} }
__ bind(&try_float);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
__ cmp(r1, heap_number_map); __ cmp(r1, heap_number_map);
@ -2344,6 +2367,19 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ mov(r0, Operand(r1)); __ mov(r0, Operand(r1));
} }
} else if (op_ == Token::BIT_NOT) { } else if (op_ == Token::BIT_NOT) {
if (include_smi_code_) {
Label non_smi;
__ BranchOnNotSmi(r0, &non_smi);
__ mvn(r0, Operand(r0));
// Bit-clear inverted smi-tag.
__ bic(r0, r0, Operand(kSmiTagMask));
__ Ret();
__ bind(&non_smi);
} else if (FLAG_debug_code) {
__ tst(r0, Operand(kSmiTagMask));
__ Assert(ne, "Unexpected smi operand.");
}
// Check if the operand is a heap number. // Check if the operand is a heap number.
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
@ -2391,7 +2427,7 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
} }
__ bind(&done); __ bind(&done);
__ StubReturn(1); __ Ret();
// Handle the slow case by jumping to the JavaScript builtin. // Handle the slow case by jumping to the JavaScript builtin.
__ bind(&slow); __ bind(&slow);
@ -3499,6 +3535,11 @@ const char* CompareStub::GetName() {
include_number_compare_name = "_NO_NUMBER"; include_number_compare_name = "_NO_NUMBER";
} }
const char* include_smi_compare_name = "";
if (!include_smi_compare_) {
include_smi_compare_name = "_NO_SMI";
}
OS::SNPrintF(Vector<char>(name_, kMaxNameLength), OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
"CompareStub_%s%s%s%s%s%s", "CompareStub_%s%s%s%s%s%s",
cc_name, cc_name,
@ -3506,7 +3547,8 @@ const char* CompareStub::GetName() {
rhs_name, rhs_name,
strict_name, strict_name,
never_nan_nan_name, never_nan_nan_name,
include_number_compare_name); include_number_compare_name,
include_smi_compare_name);
return name_; return name_;
} }
@ -3522,7 +3564,8 @@ int CompareStub::MinorKey() {
| RegisterField::encode(lhs_.is(r0)) | RegisterField::encode(lhs_.is(r0))
| StrictField::encode(strict_) | StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_); | IncludeNumberCompareField::encode(include_number_compare_)
| IncludeSmiCompareField::encode(include_smi_compare_);
} }

View File

@ -1651,7 +1651,7 @@ void CodeGenerator::Comparison(Condition cc,
// Perform non-smi comparison by stub. // Perform non-smi comparison by stub.
// CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0. // CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0.
// We call with 0 args because there are 0 on the stack. // We call with 0 args because there are 0 on the stack.
CompareStub stub(cc, strict, kBothCouldBeNaN, true, lhs, rhs); CompareStub stub(cc, strict, NO_SMI_COMPARE_IN_STUB, lhs, rhs);
frame_->CallStub(&stub, 0); frame_->CallStub(&stub, 0);
__ cmp(r0, Operand(0, RelocInfo::NONE)); __ cmp(r0, Operand(0, RelocInfo::NONE));
exit.Jump(); exit.Jump();
@ -5985,6 +5985,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
GenericUnaryOpStub stub( GenericUnaryOpStub stub(
Token::SUB, Token::SUB,
overwrite, overwrite,
NO_UNARY_FLAGS,
no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero); no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero);
frame_->CallStub(&stub, 0); frame_->CallStub(&stub, 0);
frame_->EmitPush(r0); // r0 has result frame_->EmitPush(r0); // r0 has result
@ -6009,7 +6010,9 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
not_smi_label.Bind(); not_smi_label.Bind();
frame_->SpillAll(); frame_->SpillAll();
__ Move(r0, tos); __ Move(r0, tos);
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); GenericUnaryOpStub stub(Token::BIT_NOT,
overwrite,
NO_UNARY_SMI_CODE_IN_STUB);
frame_->CallStub(&stub, 0); frame_->CallStub(&stub, 0);
frame_->EmitPush(r0); frame_->EmitPush(r0);

View File

@ -672,7 +672,8 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Perform the comparison as if via '==='. // Perform the comparison as if via '==='.
__ ldr(r1, MemOperand(sp, 0)); // Switch value. __ ldr(r1, MemOperand(sp, 0)); // Switch value.
if (ShouldInlineSmiCase(Token::EQ_STRICT)) { bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
if (inline_smi_code) {
Label slow_case; Label slow_case;
__ orr(r2, r1, r0); __ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask)); __ tst(r2, Operand(kSmiTagMask));
@ -684,7 +685,10 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&slow_case); __ bind(&slow_case);
} }
CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0); CompareFlags flags = inline_smi_code
? NO_SMI_COMPARE_IN_STUB
: NO_COMPARE_FLAGS;
CompareStub stub(eq, true, flags, r1, r0);
__ CallStub(&stub); __ CallStub(&stub);
__ cmp(r0, Operand(0, RelocInfo::NONE)); __ cmp(r0, Operand(0, RelocInfo::NONE));
__ b(ne, &next_test); __ b(ne, &next_test);
@ -2888,7 +2892,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite = UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite); GenericUnaryOpStub stub(Token::SUB,
overwrite,
NO_UNARY_FLAGS);
// GenericUnaryOpStub expects the argument to be in the // GenericUnaryOpStub expects the argument to be in the
// accumulator register r0. // accumulator register r0.
VisitForValue(expr->expression(), kAccumulator); VisitForValue(expr->expression(), kAccumulator);
@ -2903,7 +2909,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// in the accumulator register r0. // in the accumulator register r0.
VisitForValue(expr->expression(), kAccumulator); VisitForValue(expr->expression(), kAccumulator);
Label done; Label done;
if (ShouldInlineSmiCase(expr->op())) { bool inline_smi_code = ShouldInlineSmiCase(expr->op());
if (inline_smi_code) {
Label call_stub; Label call_stub;
__ BranchOnNotSmi(r0, &call_stub); __ BranchOnNotSmi(r0, &call_stub);
__ mvn(r0, Operand(r0)); __ mvn(r0, Operand(r0));
@ -2913,9 +2920,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
__ bind(&call_stub); __ bind(&call_stub);
} }
bool overwrite = expr->expression()->ResultOverwriteAllowed(); bool overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOpFlags flags = inline_smi_code
? NO_UNARY_SMI_CODE_IN_STUB
: NO_UNARY_FLAGS;
UnaryOverwriteMode mode = UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, mode); GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ bind(&done); __ bind(&done);
Apply(context_, r0); Apply(context_, r0);
@ -3292,7 +3302,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE(); UNREACHABLE();
} }
if (ShouldInlineSmiCase(op)) { bool inline_smi_code = ShouldInlineSmiCase(op);
if (inline_smi_code) {
Label slow_case; Label slow_case;
__ orr(r2, r0, Operand(r1)); __ orr(r2, r0, Operand(r1));
__ BranchOnNotSmi(r2, &slow_case); __ BranchOnNotSmi(r2, &slow_case);
@ -3300,8 +3311,10 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Split(cc, if_true, if_false, NULL); Split(cc, if_true, if_false, NULL);
__ bind(&slow_case); __ bind(&slow_case);
} }
CompareFlags flags = inline_smi_code
CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); ? NO_SMI_COMPARE_IN_STUB
: NO_COMPARE_FLAGS;
CompareStub stub(cc, strict, flags, r1, r0);
__ CallStub(&stub); __ CallStub(&stub);
__ cmp(r0, Operand(0, RelocInfo::NONE)); __ cmp(r0, Operand(0, RelocInfo::NONE));
Split(cc, if_true, if_false, fall_through); Split(cc, if_true, if_false, fall_through);

View File

@ -1242,15 +1242,6 @@ void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
} }
void MacroAssembler::StubReturn(int argc, Condition cond) {
ASSERT(argc >= 1 && generating_stub());
if (argc > 1) {
add(sp, sp, Operand((argc - 1) * kPointerSize), LeaveCC, cond);
}
Ret(cond);
}
void MacroAssembler::IllegalOperation(int num_arguments) { void MacroAssembler::IllegalOperation(int num_arguments) {
if (num_arguments > 0) { if (num_arguments > 0) {
add(sp, sp, Operand(num_arguments * kPointerSize)); add(sp, sp, Operand(num_arguments * kPointerSize));

View File

@ -531,9 +531,6 @@ class MacroAssembler: public Assembler {
// Call a code stub. // Call a code stub.
void TailCallStub(CodeStub* stub, Condition cond = al); void TailCallStub(CodeStub* stub, Condition cond = al);
// Return from a code stub after popping its arguments.
void StubReturn(int argc, Condition cond = al);
// Call a runtime routine. // Call a runtime routine.
void CallRuntime(Runtime::Function* f, int num_arguments); void CallRuntime(Runtime::Function* f, int num_arguments);

View File

@ -340,27 +340,40 @@ enum NegativeZeroHandling {
}; };
enum UnaryOpFlags {
NO_UNARY_FLAGS = 0,
NO_UNARY_SMI_CODE_IN_STUB = 1 << 0
};
class GenericUnaryOpStub : public CodeStub { class GenericUnaryOpStub : public CodeStub {
public: public:
GenericUnaryOpStub(Token::Value op, GenericUnaryOpStub(Token::Value op,
UnaryOverwriteMode overwrite, UnaryOverwriteMode overwrite,
UnaryOpFlags flags,
NegativeZeroHandling negative_zero = kStrictNegativeZero) NegativeZeroHandling negative_zero = kStrictNegativeZero)
: op_(op), overwrite_(overwrite), negative_zero_(negative_zero) { } : op_(op),
overwrite_(overwrite),
include_smi_code_((flags & NO_UNARY_SMI_CODE_IN_STUB) == 0),
negative_zero_(negative_zero) { }
private: private:
Token::Value op_; Token::Value op_;
UnaryOverwriteMode overwrite_; UnaryOverwriteMode overwrite_;
bool include_smi_code_;
NegativeZeroHandling negative_zero_; NegativeZeroHandling negative_zero_;
class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {}; class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {};
class NegativeZeroField: public BitField<NegativeZeroHandling, 1, 1> {}; class IncludeSmiCodeField: public BitField<bool, 1, 1> {};
class OpField: public BitField<Token::Value, 2, kMinorBits - 2> {}; class NegativeZeroField: public BitField<NegativeZeroHandling, 2, 1> {};
class OpField: public BitField<Token::Value, 3, kMinorBits - 3> {};
Major MajorKey() { return GenericUnaryOp; } Major MajorKey() { return GenericUnaryOp; }
int MinorKey() { int MinorKey() {
return OpField::encode(op_) | return OpField::encode(op_) |
OverwriteField::encode(overwrite_) | OverwriteField::encode(overwrite_) |
NegativeZeroField::encode(negative_zero_); IncludeSmiCodeField::encode(include_smi_code_) |
NegativeZeroField::encode(negative_zero_);
} }
void Generate(MacroAssembler* masm); void Generate(MacroAssembler* masm);
@ -375,22 +388,43 @@ enum NaNInformation {
}; };
// Flags that control the compare stub code generation.
enum CompareFlags {
NO_COMPARE_FLAGS = 0,
NO_SMI_COMPARE_IN_STUB = 1 << 0,
NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
CANT_BOTH_BE_NAN = 1 << 2
};
class CompareStub: public CodeStub { class CompareStub: public CodeStub {
public: public:
CompareStub(Condition cc, CompareStub(Condition cc,
bool strict, bool strict,
NaNInformation nan_info = kBothCouldBeNaN, CompareFlags flags,
bool include_number_compare = true, Register lhs,
Register lhs = no_reg, Register rhs) :
Register rhs = no_reg) :
cc_(cc), cc_(cc),
strict_(strict), strict_(strict),
never_nan_nan_(nan_info == kCantBothBeNaN), never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
include_number_compare_(include_number_compare), include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
lhs_(lhs), lhs_(lhs),
rhs_(rhs), rhs_(rhs),
name_(NULL) { } name_(NULL) { }
CompareStub(Condition cc,
bool strict,
CompareFlags flags) :
cc_(cc),
strict_(strict),
never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
lhs_(no_reg),
rhs_(no_reg),
name_(NULL) { }
void Generate(MacroAssembler* masm); void Generate(MacroAssembler* masm);
private: private:
@ -406,6 +440,10 @@ class CompareStub: public CodeStub {
// comparison code is used when the number comparison has been inlined, and // comparison code is used when the number comparison has been inlined, and
// the stub will be called if one of the operands is not a number. // the stub will be called if one of the operands is not a number.
bool include_number_compare_; bool include_number_compare_;
// Generate the comparison code for two smi operands in the stub.
bool include_smi_compare_;
// Register holding the left hand side of the comparison if the stub gives // Register holding the left hand side of the comparison if the stub gives
// a choice, no_reg otherwise. // a choice, no_reg otherwise.
Register lhs_; Register lhs_;
@ -413,12 +451,13 @@ class CompareStub: public CodeStub {
// a choice, no_reg otherwise. // a choice, no_reg otherwise.
Register rhs_; Register rhs_;
// Encoding of the minor key CCCCCCCCCCCCRCNS. // Encoding of the minor key in 16 bits.
class StrictField: public BitField<bool, 0, 1> {}; class StrictField: public BitField<bool, 0, 1> {};
class NeverNanNanField: public BitField<bool, 1, 1> {}; class NeverNanNanField: public BitField<bool, 1, 1> {};
class IncludeNumberCompareField: public BitField<bool, 2, 1> {}; class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
class RegisterField: public BitField<bool, 3, 1> {}; class IncludeSmiCompareField: public BitField<bool, 3, 1> {};
class ConditionField: public BitField<int, 4, 12> {}; class RegisterField: public BitField<bool, 4, 1> {};
class ConditionField: public BitField<int, 5, 11> {};
Major MajorKey() { return Compare; } Major MajorKey() { return Compare; }
@ -436,11 +475,13 @@ class CompareStub: public CodeStub {
const char* GetName(); const char* GetName();
#ifdef DEBUG #ifdef DEBUG
void Print() { void Print() {
PrintF("CompareStub (cc %d), (strict %s), " PrintF("CompareStub (minor %d) (cc %d), (strict %s), "
"(never_nan_nan %s), (number_compare %s) ", "(never_nan_nan %s), (smi_compare %s) (number_compare %s) ",
MinorKey(),
static_cast<int>(cc_), static_cast<int>(cc_),
strict_ ? "true" : "false", strict_ ? "true" : "false",
never_nan_nan_ ? "true" : "false", never_nan_nan_ ? "true" : "false",
include_smi_compare_ ? "inluded" : "not included",
include_number_compare_ ? "included" : "not included"); include_number_compare_ ? "included" : "not included");
if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) { if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {

View File

@ -174,6 +174,10 @@ DEFINE_bool(enable_liveedit, true, "enable liveedit experimental feature")
DEFINE_int(max_stack_trace_source_length, 300, DEFINE_int(max_stack_trace_source_length, 300,
"maximum length of function source code printed in a stack trace.") "maximum length of function source code printed in a stack trace.")
// full-codegen.cc
DEFINE_bool(always_inline_smi_code, false,
"always inline smi code in non-opt code")
// heap.cc // heap.cc
DEFINE_int(max_new_space_size, 0, "max size of the new generation") DEFINE_int(max_new_space_size, 0, "max size of the new generation")
DEFINE_int(max_old_space_size, 0, "max size of the old generation") DEFINE_int(max_old_space_size, 0, "max size of the old generation")

View File

@ -324,15 +324,11 @@ int FullCodeGenerator::SlotOffset(Slot* slot) {
bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
// TODO(kasperl): Once the compare stub allows leaving out the
// inlined smi case, we should get rid of this check.
if (Token::IsCompareOp(op)) return true;
// TODO(kasperl): Once the unary bit not stub allows leaving out
// the inlined smi case, we should get rid of this check.
if (op == Token::BIT_NOT) return true;
// Inline smi case inside loops, but not division and modulo which // Inline smi case inside loops, but not division and modulo which
// are too complicated and take up too much space. // are too complicated and take up too much space.
return (op != Token::DIV) && (op != Token::MOD) && (loop_depth_ > 0); if (op == Token::DIV ||op == Token::MOD) return false;
if (FLAG_always_inline_smi_code) return true;
return loop_depth_ > 0;
} }

View File

@ -1879,36 +1879,36 @@ void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
void GenericUnaryOpStub::Generate(MacroAssembler* masm) { void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
Label slow, done; Label slow, done, undo;
if (op_ == Token::SUB) { if (op_ == Token::SUB) {
// Check whether the value is a smi. if (include_smi_code_) {
Label try_float; // Check whether the value is a smi.
__ test(eax, Immediate(kSmiTagMask)); Label try_float;
__ j(not_zero, &try_float, not_taken); __ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &try_float, not_taken);
if (negative_zero_ == kStrictNegativeZero) { if (negative_zero_ == kStrictNegativeZero) {
// Go slow case if the value of the expression is zero // Go slow case if the value of the expression is zero
// to make sure that we switch between 0 and -0. // to make sure that we switch between 0 and -0.
__ test(eax, Operand(eax)); __ test(eax, Operand(eax));
__ j(zero, &slow, not_taken); __ j(zero, &slow, not_taken);
}
// The value of the expression is a smi that is not zero. Try
// optimistic subtraction '0 - value'.
__ mov(edx, Operand(eax));
__ Set(eax, Immediate(0));
__ sub(eax, Operand(edx));
__ j(overflow, &undo, not_taken);
__ StubReturn(1);
// Try floating point case.
__ bind(&try_float);
} else if (FLAG_debug_code) {
__ AbortIfSmi(eax);
} }
// The value of the expression is a smi that is not zero. Try
// optimistic subtraction '0 - value'.
Label undo;
__ mov(edx, Operand(eax));
__ Set(eax, Immediate(0));
__ sub(eax, Operand(edx));
__ j(no_overflow, &done, taken);
// Restore eax and go slow case.
__ bind(&undo);
__ mov(eax, Operand(edx));
__ jmp(&slow);
// Try floating point case.
__ bind(&try_float);
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(edx, Factory::heap_number_map()); __ cmp(edx, Factory::heap_number_map());
__ j(not_equal, &slow); __ j(not_equal, &slow);
@ -1928,6 +1928,18 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
} }
} else if (op_ == Token::BIT_NOT) { } else if (op_ == Token::BIT_NOT) {
if (include_smi_code_) {
Label non_smi;
__ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &non_smi);
__ not_(eax);
__ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag.
__ ret(0);
__ bind(&non_smi);
} else if (FLAG_debug_code) {
__ AbortIfSmi(eax);
}
// Check if the operand is a heap number. // Check if the operand is a heap number.
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(edx, Factory::heap_number_map()); __ cmp(edx, Factory::heap_number_map());
@ -1978,6 +1990,10 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ bind(&done); __ bind(&done);
__ StubReturn(1); __ StubReturn(1);
// Restore eax and go slow case.
__ bind(&undo);
__ mov(eax, Operand(edx));
// Handle the slow case by jumping to the JavaScript builtin. // Handle the slow case by jumping to the JavaScript builtin.
__ bind(&slow); __ bind(&slow);
__ pop(ecx); // pop return address. __ pop(ecx); // pop return address.
@ -2613,6 +2629,27 @@ void CompareStub::Generate(MacroAssembler* masm) {
Label check_unequal_objects, done; Label check_unequal_objects, done;
// Compare two smis if required.
if (include_smi_compare_) {
Label non_smi, smi_done;
__ mov(ecx, Operand(edx));
__ or_(ecx, Operand(eax));
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &non_smi, not_taken);
__ sub(edx, Operand(eax)); // Return on the result of the subtraction.
__ j(no_overflow, &smi_done);
__ neg(edx); // Correct sign in case of overflow.
__ bind(&smi_done);
__ mov(eax, edx);
__ ret(0);
__ bind(&non_smi);
} else if (FLAG_debug_code) {
__ mov(ecx, Operand(edx));
__ or_(ecx, Operand(eax));
__ test(ecx, Immediate(kSmiTagMask));
__ Assert(not_zero, "Unexpected smi operands.");
}
// NOTICE! This code is only reached after a smi-fast-case check, so // NOTICE! This code is only reached after a smi-fast-case check, so
// it is certain that at least one operand isn't a smi. // it is certain that at least one operand isn't a smi.
@ -3501,7 +3538,8 @@ int CompareStub::MinorKey() {
| RegisterField::encode(false) // lhs_ and rhs_ are not used | RegisterField::encode(false) // lhs_ and rhs_ are not used
| StrictField::encode(strict_) | StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_); | IncludeNumberCompareField::encode(include_number_compare_)
| IncludeSmiCompareField::encode(include_smi_compare_);
} }
@ -3541,12 +3579,18 @@ const char* CompareStub::GetName() {
include_number_compare_name = "_NO_NUMBER"; include_number_compare_name = "_NO_NUMBER";
} }
const char* include_smi_compare_name = "";
if (!include_smi_compare_) {
include_smi_compare_name = "_NO_SMI";
}
OS::SNPrintF(Vector<char>(name_, kMaxNameLength), OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
"CompareStub_%s%s%s%s", "CompareStub_%s%s%s%s%s",
cc_name, cc_name,
strict_name, strict_name,
never_nan_nan_name, never_nan_nan_name,
include_number_compare_name); include_number_compare_name,
include_smi_compare_name);
return name_; return name_;
} }

View File

@ -2646,6 +2646,19 @@ static Condition DoubleCondition(Condition cc) {
} }
static CompareFlags ComputeCompareFlags(NaNInformation nan_info,
bool inline_number_compare) {
CompareFlags flags = NO_SMI_COMPARE_IN_STUB;
if (nan_info == kCantBothBeNaN) {
flags = static_cast<CompareFlags>(flags | CANT_BOTH_BE_NAN);
}
if (inline_number_compare) {
flags = static_cast<CompareFlags>(flags | NO_NUMBER_COMPARE_IN_STUB);
}
return flags;
}
void CodeGenerator::Comparison(AstNode* node, void CodeGenerator::Comparison(AstNode* node,
Condition cc, Condition cc,
bool strict, bool strict,
@ -2773,7 +2786,9 @@ void CodeGenerator::Comparison(AstNode* node,
// Setup and call the compare stub. // Setup and call the compare stub.
is_not_string.Bind(&left_side); is_not_string.Bind(&left_side);
CompareStub stub(cc, strict, kCantBothBeNaN); CompareFlags flags =
static_cast<CompareFlags>(CANT_BOTH_BE_NAN | NO_SMI_COMPARE_IN_STUB);
CompareStub stub(cc, strict, flags);
Result result = frame_->CallStub(&stub, &left_side, &right_side); Result result = frame_->CallStub(&stub, &left_side, &right_side);
result.ToRegister(); result.ToRegister();
__ cmp(result.reg(), 0); __ cmp(result.reg(), 0);
@ -2867,7 +2882,8 @@ void CodeGenerator::Comparison(AstNode* node,
// End of in-line compare, call out to the compare stub. Don't include // End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined. // number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare); CompareFlags flags = ComputeCompareFlags(nan_info, inline_number_compare);
CompareStub stub(cc, strict, flags);
Result answer = frame_->CallStub(&stub, &left_side, &right_side); Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ test(answer.reg(), Operand(answer.reg())); __ test(answer.reg(), Operand(answer.reg()));
answer.Unuse(); answer.Unuse();
@ -2900,7 +2916,9 @@ void CodeGenerator::Comparison(AstNode* node,
// End of in-line compare, call out to the compare stub. Don't include // End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined. // number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare); CompareFlags flags =
ComputeCompareFlags(nan_info, inline_number_compare);
CompareStub stub(cc, strict, flags);
Result answer = frame_->CallStub(&stub, &left_side, &right_side); Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ test(answer.reg(), Operand(answer.reg())); __ test(answer.reg(), Operand(answer.reg()));
answer.Unuse(); answer.Unuse();
@ -2994,7 +3012,6 @@ void CodeGenerator::ConstantSmiComparison(Condition cc,
dest->false_target()->Branch(zero); dest->false_target()->Branch(zero);
} else { } else {
// Do the smi check, then the comparison. // Do the smi check, then the comparison.
JumpTarget is_not_smi;
__ test(left_reg, Immediate(kSmiTagMask)); __ test(left_reg, Immediate(kSmiTagMask));
is_smi.Branch(zero, left_side, right_side); is_smi.Branch(zero, left_side, right_side);
} }
@ -3031,7 +3048,9 @@ void CodeGenerator::ConstantSmiComparison(Condition cc,
} }
// Setup and call the compare stub. // Setup and call the compare stub.
CompareStub stub(cc, strict, kCantBothBeNaN); CompareFlags flags =
static_cast<CompareFlags>(CANT_BOTH_BE_NAN | NO_SMI_CODE_IN_STUB);
CompareStub stub(cc, strict, flags);
Result result = frame_->CallStub(&stub, left_side, right_side); Result result = frame_->CallStub(&stub, left_side, right_side);
result.ToRegister(); result.ToRegister();
__ test(result.reg(), Operand(result.reg())); __ test(result.reg(), Operand(result.reg()));
@ -8146,6 +8165,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
GenericUnaryOpStub stub( GenericUnaryOpStub stub(
Token::SUB, Token::SUB,
overwrite, overwrite,
NO_UNARY_FLAGS,
no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero); no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero);
Result operand = frame_->Pop(); Result operand = frame_->Pop();
Result answer = frame_->CallStub(&stub, &operand); Result answer = frame_->CallStub(&stub, &operand);
@ -8173,7 +8193,9 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
__ test(operand.reg(), Immediate(kSmiTagMask)); __ test(operand.reg(), Immediate(kSmiTagMask));
smi_label.Branch(zero, &operand, taken); smi_label.Branch(zero, &operand, taken);
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); GenericUnaryOpStub stub(Token::BIT_NOT,
overwrite,
NO_UNARY_SMI_CODE_IN_STUB);
Result answer = frame_->CallStub(&stub, &operand); Result answer = frame_->CallStub(&stub, &operand);
continue_label.Jump(&answer); continue_label.Jump(&answer);

View File

@ -684,7 +684,8 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Perform the comparison as if via '==='. // Perform the comparison as if via '==='.
__ mov(edx, Operand(esp, 0)); // Switch value. __ mov(edx, Operand(esp, 0)); // Switch value.
if (ShouldInlineSmiCase(Token::EQ_STRICT)) { bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
if (inline_smi_code) {
Label slow_case; Label slow_case;
__ mov(ecx, edx); __ mov(ecx, edx);
__ or_(ecx, Operand(eax)); __ or_(ecx, Operand(eax));
@ -697,7 +698,10 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&slow_case); __ bind(&slow_case);
} }
CompareStub stub(equal, true); CompareFlags flags = inline_smi_code
? NO_SMI_COMPARE_IN_STUB
: NO_COMPARE_FLAGS;
CompareStub stub(equal, true, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ test(eax, Operand(eax)); __ test(eax, Operand(eax));
__ j(not_equal, &next_test); __ j(not_equal, &next_test);
@ -3258,7 +3262,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite = UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite); GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS);
// GenericUnaryOpStub expects the argument to be in the // GenericUnaryOpStub expects the argument to be in the
// accumulator register eax. // accumulator register eax.
VisitForValue(expr->expression(), kAccumulator); VisitForValue(expr->expression(), kAccumulator);
@ -3273,7 +3277,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// in the accumulator register eax. // in the accumulator register eax.
VisitForValue(expr->expression(), kAccumulator); VisitForValue(expr->expression(), kAccumulator);
Label done; Label done;
if (ShouldInlineSmiCase(expr->op())) { bool inline_smi_case = ShouldInlineSmiCase(expr->op());
if (inline_smi_case) {
Label call_stub; Label call_stub;
__ test(eax, Immediate(kSmiTagMask)); __ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &call_stub); __ j(not_zero, &call_stub);
@ -3285,7 +3290,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
bool overwrite = expr->expression()->ResultOverwriteAllowed(); bool overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode mode = UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, mode); UnaryOpFlags flags = inline_smi_case
? NO_UNARY_SMI_CODE_IN_STUB
: NO_UNARY_FLAGS;
GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ bind(&done); __ bind(&done);
Apply(context_, eax); Apply(context_, eax);
@ -3674,7 +3682,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE(); UNREACHABLE();
} }
if (ShouldInlineSmiCase(op)) { bool inline_smi_code = ShouldInlineSmiCase(op);
if (inline_smi_code) {
Label slow_case; Label slow_case;
__ mov(ecx, Operand(edx)); __ mov(ecx, Operand(edx));
__ or_(ecx, Operand(eax)); __ or_(ecx, Operand(eax));
@ -3685,7 +3694,10 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
__ bind(&slow_case); __ bind(&slow_case);
} }
CompareStub stub(cc, strict); CompareFlags flags = inline_smi_code
? NO_SMI_COMPARE_IN_STUB
: NO_COMPARE_FLAGS;
CompareStub stub(cc, strict, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ test(eax, Operand(eax)); __ test(eax, Operand(eax));
Split(cc, if_true, if_false, fall_through); Split(cc, if_true, if_false, fall_through);

View File

@ -1404,33 +1404,35 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
Label slow, done; Label slow, done;
if (op_ == Token::SUB) { if (op_ == Token::SUB) {
// Check whether the value is a smi. if (include_smi_code_) {
Label try_float; // Check whether the value is a smi.
__ JumpIfNotSmi(rax, &try_float); Label try_float;
__ JumpIfNotSmi(rax, &try_float);
if (negative_zero_ == kIgnoreNegativeZero) {
__ SmiCompare(rax, Smi::FromInt(0));
__ j(equal, &done);
}
__ SmiNeg(rax, rax, &done);
if (negative_zero_ == kIgnoreNegativeZero) { // Either zero or Smi::kMinValue, neither of which become a smi when
__ SmiCompare(rax, Smi::FromInt(0)); // negated. We handle negative zero here if required. We always enter
__ j(equal, &done); // the runtime system if we have Smi::kMinValue.
if (negative_zero_ == kStrictNegativeZero) {
__ SmiCompare(rax, Smi::FromInt(0));
__ j(not_equal, &slow);
__ Move(rax, Factory::minus_zero_value());
__ jmp(&done);
} else {
__ SmiCompare(rax, Smi::FromInt(Smi::kMinValue));
__ j(equal, &slow);
__ jmp(&done);
}
// Try floating point case.
__ bind(&try_float);
} else if (FLAG_debug_code) {
__ AbortIfSmi(rax);
} }
// Enter runtime system if the value of the smi is zero
// to make sure that we switch between 0 and -0.
// Also enter it if the value of the smi is Smi::kMinValue.
__ SmiNeg(rax, rax, &done);
// Either zero or Smi::kMinValue, neither of which become a smi when
// negated.
if (negative_zero_ == kStrictNegativeZero) {
__ SmiCompare(rax, Smi::FromInt(0));
__ j(not_equal, &slow);
__ Move(rax, Factory::minus_zero_value());
__ jmp(&done);
} else {
__ jmp(&slow);
}
// Try floating point case.
__ bind(&try_float);
__ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
__ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
__ j(not_equal, &slow); __ j(not_equal, &slow);
@ -1449,6 +1451,17 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ movq(rax, rcx); __ movq(rax, rcx);
} }
} else if (op_ == Token::BIT_NOT) { } else if (op_ == Token::BIT_NOT) {
if (include_smi_code_) {
Label try_float;
__ JumpIfNotSmi(rax, &try_float);
__ SmiNot(rax, rax);
__ jmp(&done);
// Try floating point case.
__ bind(&try_float);
} else if (FLAG_debug_code) {
__ AbortIfSmi(rax);
}
// Check if the operand is a heap number. // Check if the operand is a heap number.
__ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
__ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
@ -2115,6 +2128,26 @@ void CompareStub::Generate(MacroAssembler* masm) {
ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
Label check_unequal_objects, done; Label check_unequal_objects, done;
// Compare two smis if required.
if (include_smi_compare_) {
Label non_smi, smi_done;
__ JumpIfNotBothSmi(rax, rdx, &non_smi);
__ subq(rdx, rax);
__ j(no_overflow, &smi_done);
__ neg(rdx); // Correct sign in case of overflow.
__ bind(&smi_done);
__ movq(rax, rdx);
__ ret(0);
__ bind(&non_smi);
} else if (FLAG_debug_code) {
Label ok;
__ JumpIfNotSmi(rdx, &ok);
__ JumpIfNotSmi(rax, &ok);
__ Abort("CompareStub: smi operands");
__ bind(&ok);
}
// The compare stub returns a positive, negative, or zero 64-bit integer // The compare stub returns a positive, negative, or zero 64-bit integer
// value in rax, corresponding to result of comparing the two inputs. // value in rax, corresponding to result of comparing the two inputs.
// NOTICE! This code is only reached after a smi-fast-case check, so // NOTICE! This code is only reached after a smi-fast-case check, so
@ -3001,7 +3034,8 @@ int CompareStub::MinorKey() {
| RegisterField::encode(false) // lhs_ and rhs_ are not used | RegisterField::encode(false) // lhs_ and rhs_ are not used
| StrictField::encode(strict_) | StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_); | IncludeNumberCompareField::encode(include_number_compare_)
| IncludeSmiCompareField::encode(include_smi_compare_);
} }
@ -3041,12 +3075,18 @@ const char* CompareStub::GetName() {
include_number_compare_name = "_NO_NUMBER"; include_number_compare_name = "_NO_NUMBER";
} }
const char* include_smi_compare_name = "";
if (!include_smi_compare_) {
include_smi_compare_name = "_NO_SMI";
}
OS::SNPrintF(Vector<char>(name_, kMaxNameLength), OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
"CompareStub_%s%s%s%s", "CompareStub_%s%s%s%s",
cc_name, cc_name,
strict_name, strict_name,
never_nan_nan_name, never_nan_nan_name,
include_number_compare_name); include_number_compare_name,
include_smi_compare_name);
return name_; return name_;
} }

View File

@ -1940,6 +1940,19 @@ static Condition DoubleCondition(Condition cc) {
} }
static CompareFlags ComputeCompareFlags(NaNInformation nan_info,
bool inline_number_compare) {
CompareFlags flags = NO_SMI_COMPARE_IN_STUB;
if (nan_info == kCantBothBeNaN) {
flags = static_cast<CompareFlags>(flags | CANT_BOTH_BE_NAN);
}
if (inline_number_compare) {
flags = static_cast<CompareFlags>(flags | NO_NUMBER_COMPARE_IN_STUB);
}
return flags;
}
void CodeGenerator::Comparison(AstNode* node, void CodeGenerator::Comparison(AstNode* node,
Condition cc, Condition cc,
bool strict, bool strict,
@ -2070,7 +2083,9 @@ void CodeGenerator::Comparison(AstNode* node,
// Setup and call the compare stub. // Setup and call the compare stub.
is_not_string.Bind(&left_side); is_not_string.Bind(&left_side);
CompareStub stub(cc, strict, kCantBothBeNaN); CompareFlags flags =
static_cast<CompareFlags>(CANT_BOTH_BE_NAN | NO_SMI_CODE_IN_STUB);
CompareStub stub(cc, strict, flags);
Result result = frame_->CallStub(&stub, &left_side, &right_side); Result result = frame_->CallStub(&stub, &left_side, &right_side);
result.ToRegister(); result.ToRegister();
__ testq(result.reg(), result.reg()); __ testq(result.reg(), result.reg());
@ -2174,7 +2189,8 @@ void CodeGenerator::Comparison(AstNode* node,
// End of in-line compare, call out to the compare stub. Don't include // End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined. // number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare); CompareFlags flags = ComputeCompareFlags(nan_info, inline_number_compare);
CompareStub stub(cc, strict, flags);
Result answer = frame_->CallStub(&stub, &left_side, &right_side); Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ testq(answer.reg(), answer.reg()); // Sets both zero and sign flag. __ testq(answer.reg(), answer.reg()); // Sets both zero and sign flag.
answer.Unuse(); answer.Unuse();
@ -2207,7 +2223,9 @@ void CodeGenerator::Comparison(AstNode* node,
// End of in-line compare, call out to the compare stub. Don't include // End of in-line compare, call out to the compare stub. Don't include
// number comparison in the stub if it was inlined. // number comparison in the stub if it was inlined.
CompareStub stub(cc, strict, nan_info, !inline_number_compare); CompareFlags flags =
ComputeCompareFlags(nan_info, inline_number_compare);
CompareStub stub(cc, strict, flags);
Result answer = frame_->CallStub(&stub, &left_side, &right_side); Result answer = frame_->CallStub(&stub, &left_side, &right_side);
__ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags. __ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags.
answer.Unuse(); answer.Unuse();
@ -2332,7 +2350,9 @@ void CodeGenerator::ConstantSmiComparison(Condition cc,
} }
// Setup and call the compare stub. // Setup and call the compare stub.
CompareStub stub(cc, strict, kCantBothBeNaN); CompareFlags flags =
static_cast<CompareFlags>(CANT_BOTH_BE_NAN | NO_SMI_CODE_IN_STUB);
CompareStub stub(cc, strict, flags);
Result result = frame_->CallStub(&stub, left_side, right_side); Result result = frame_->CallStub(&stub, left_side, right_side);
result.ToRegister(); result.ToRegister();
__ testq(result.reg(), result.reg()); __ testq(result.reg(), result.reg());
@ -7395,6 +7415,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
GenericUnaryOpStub stub( GenericUnaryOpStub stub(
Token::SUB, Token::SUB,
overwrite, overwrite,
NO_UNARY_FLAGS,
no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero); no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero);
Result operand = frame_->Pop(); Result operand = frame_->Pop();
Result answer = frame_->CallStub(&stub, &operand); Result answer = frame_->CallStub(&stub, &operand);
@ -7413,7 +7434,9 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
Condition is_smi = masm_->CheckSmi(operand.reg()); Condition is_smi = masm_->CheckSmi(operand.reg());
smi_label.Branch(is_smi, &operand); smi_label.Branch(is_smi, &operand);
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); GenericUnaryOpStub stub(Token::BIT_NOT,
overwrite,
NO_UNARY_SMI_CODE_IN_STUB);
Result answer = frame_->CallStub(&stub, &operand); Result answer = frame_->CallStub(&stub, &operand);
continue_label.Jump(&answer); continue_label.Jump(&answer);

View File

@ -677,9 +677,10 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitForValue(clause->label(), kAccumulator); VisitForValue(clause->label(), kAccumulator);
// Perform the comparison as if via '==='. // Perform the comparison as if via '==='.
if (ShouldInlineSmiCase(Token::EQ_STRICT)) { __ movq(rdx, Operand(rsp, 0)); // Switch value.
bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
if (inline_smi_code) {
Label slow_case; Label slow_case;
__ movq(rdx, Operand(rsp, 0)); // Switch value.
__ JumpIfNotBothSmi(rdx, rax, &slow_case); __ JumpIfNotBothSmi(rdx, rax, &slow_case);
__ SmiCompare(rdx, rax); __ SmiCompare(rdx, rax);
__ j(not_equal, &next_test); __ j(not_equal, &next_test);
@ -688,7 +689,10 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&slow_case); __ bind(&slow_case);
} }
CompareStub stub(equal, true); CompareFlags flags = inline_smi_code
? NO_SMI_COMPARE_IN_STUB
: NO_COMPARE_FLAGS;
CompareStub stub(equal, true, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ testq(rax, rax); __ testq(rax, rax);
__ j(not_equal, &next_test); __ j(not_equal, &next_test);
@ -2955,7 +2959,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite = UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite); GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS);
// GenericUnaryOpStub expects the argument to be in the // GenericUnaryOpStub expects the argument to be in the
// accumulator register rax. // accumulator register rax.
VisitForValue(expr->expression(), kAccumulator); VisitForValue(expr->expression(), kAccumulator);
@ -2970,7 +2974,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// in the accumulator register rax. // in the accumulator register rax.
VisitForValue(expr->expression(), kAccumulator); VisitForValue(expr->expression(), kAccumulator);
Label done; Label done;
if (ShouldInlineSmiCase(expr->op())) { bool inline_smi_case = ShouldInlineSmiCase(expr->op());
if (inline_smi_case) {
Label call_stub; Label call_stub;
__ JumpIfNotSmi(rax, &call_stub); __ JumpIfNotSmi(rax, &call_stub);
__ SmiNot(rax, rax); __ SmiNot(rax, rax);
@ -2980,7 +2985,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
bool overwrite = expr->expression()->ResultOverwriteAllowed(); bool overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode mode = UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, mode); UnaryOpFlags flags = inline_smi_case
? NO_UNARY_SMI_CODE_IN_STUB
: NO_UNARY_FLAGS;
GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ bind(&done); __ bind(&done);
Apply(context_, rax); Apply(context_, rax);
@ -3363,7 +3371,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE(); UNREACHABLE();
} }
if (ShouldInlineSmiCase(op)) { bool inline_smi_code = ShouldInlineSmiCase(op);
if (inline_smi_code) {
Label slow_case; Label slow_case;
__ JumpIfNotBothSmi(rax, rdx, &slow_case); __ JumpIfNotBothSmi(rax, rdx, &slow_case);
__ SmiCompare(rdx, rax); __ SmiCompare(rdx, rax);
@ -3371,7 +3380,10 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
__ bind(&slow_case); __ bind(&slow_case);
} }
CompareStub stub(cc, strict); CompareFlags flags = inline_smi_code
? NO_SMI_COMPARE_IN_STUB
: NO_COMPARE_FLAGS;
CompareStub stub(cc, strict, flags);
__ CallStub(&stub); __ CallStub(&stub);
__ testq(rax, rax); __ testq(rax, rax);
Split(cc, if_true, if_false, fall_through); Split(cc, if_true, if_false, fall_through);