if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
- } else {
- if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(operand->reg());
}
deferred->BindExit();
answer = *operand;
if (!operand->type_info().IsSmi()) {
__ test(answer.reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
- } else {
- if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(operand->reg());
}
deferred->BindExit();
operand->Unuse();
}
deferred->BindExit();
} else {
- if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
+ if (FLAG_debug_code) {
+ __ AbortIfNotSmi(operand->reg());
+ }
if (shift_value > 0) {
__ sar(operand->reg(), shift_value);
__ and_(operand->reg(), ~kSmiTagMask);
if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
- } else {
- if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(operand->reg());
}
__ mov(answer.reg(), operand->reg());
__ SmiUntag(answer.reg());
case Token::SHL:
if (reversed) {
+ // Move operand into ecx and also into a second register.
+ // If operand is already in a register, take advantage of that.
+ // This lets us modify ecx, but still bail out to deferred code.
Result right;
Result right_copy_in_ecx;
-
- // Make sure to get a copy of the right operand into ecx. This
- // allows us to modify it without having to restore it in the
- // deferred code.
+ TypeInfo right_type_info = operand->type_info();
operand->ToRegister();
if (operand->reg().is(ecx)) {
right = allocator()->Allocate();
answer.reg(),
smi_value,
right.reg(),
- right.type_info(),
+ right_type_info,
overwrite_mode);
__ mov(answer.reg(), Immediate(int_value));
__ sar(ecx, kSmiTagSize);
if (!right.type_info().IsSmi()) {
deferred->Branch(carry);
- } else {
- if (FLAG_debug_code) __ AbortIfNotSmi(right.reg());
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(right.reg());
}
__ shl_cl(answer.reg());
__ cmp(answer.reg(), 0xc0000000);
if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
- } else {
- if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(operand->reg());
}
__ mov(answer.reg(), operand->reg());
ASSERT(kSmiTag == 0); // adjust code if not the case
if (!operand->type_info().IsSmi()) {
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
- } else {
- if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(operand->reg());
}
if (op == Token::BIT_AND) {
__ and_(Operand(operand->reg()), Immediate(value));
};
+// Call the appropriate binary operation stub to compute value op src
+// and leave the result in dst.
+class DeferredInlineSmiOperationReversed: public DeferredCode {
+ public:
+ DeferredInlineSmiOperationReversed(Token::Value op,
+ Register dst,
+ Smi* value,
+ Register src,
+ OverwriteMode overwrite_mode)
+ : op_(op),
+ dst_(dst),
+ value_(value),
+ src_(src),
+ overwrite_mode_(overwrite_mode) {
+ set_comment("[ DeferredInlineSmiOperationReversed");
+ }
+
+ virtual void Generate();
+
+ private:
+ Token::Value op_;
+ Register dst_;
+ Smi* value_;
+ Register src_;
+ OverwriteMode overwrite_mode_;
+};
+
+
class FloatingPointHelper : public AllStatic {
public:
// Code pattern for loading a floating point value. Input value must
}
+void DeferredInlineSmiOperationReversed::Generate() {
+ GenericBinaryOpStub stub(
+ op_,
+ overwrite_mode_,
+ NO_SMI_CODE_IN_STUB);
+ stub.GenerateCall(masm_, value_, src_);
+ if (!dst_.is(rax)) __ movq(dst_, rax);
+}
+
+
Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr,
Result* operand,
Handle<Object> value,
case Token::SHL:
if (reversed) {
- Result constant_operand(value);
- answer = LikelySmiBinaryOperation(expr, &constant_operand, operand,
- overwrite_mode);
+ // Move operand into rcx and also into a second register.
+ // If operand is already in a register, take advantage of that.
+ // This lets us modify rcx, but still bail out to deferred code.
+ Result right;
+ Result right_copy_in_rcx;
+ TypeInfo right_type_info = operand->type_info();
+ operand->ToRegister();
+ if (operand->reg().is(rcx)) {
+ right = allocator()->Allocate();
+ __ movq(right.reg(), rcx);
+ frame_->Spill(rcx);
+ right_copy_in_rcx = *operand;
+ } else {
+ right_copy_in_rcx = allocator()->Allocate(rcx);
+ __ movq(rcx, operand->reg());
+ right = *operand;
+ }
+ operand->Unuse();
+
+ answer = allocator()->Allocate();
+ DeferredInlineSmiOperationReversed* deferred =
+ new DeferredInlineSmiOperationReversed(op,
+ answer.reg(),
+ smi_value,
+ right.reg(),
+ overwrite_mode);
+ __ movq(answer.reg(), Immediate(int_value));
+ __ SmiToInteger32(rcx, rcx);
+ if (!right.type_info().IsSmi()) {
+ Condition is_smi = masm_->CheckSmi(right.reg());
+ deferred->Branch(NegateCondition(is_smi));
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(right.reg(),
+ "Static type info claims non-smi is smi in (const SHL smi).");
+ }
+ __ shl_cl(answer.reg());
+ __ Integer32ToSmi(answer.reg(), answer.reg());
+
+ deferred->BindExit();
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
// Check that the key is a smi.
if (!key.is_smi()) {
__ JumpIfNotSmi(key.reg(), deferred->entry_label());
- } else {
- if (FLAG_debug_code) {
- __ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value.");
- }
+ } else if (FLAG_debug_code) {
+ __ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value.");
}
// Check that the receiver is a JSArray.
Label not_floats;
// rax: y
// rdx: x
- if (static_operands_type_.IsNumber()) {
- if (FLAG_debug_code) {
- // Assert at runtime that inputs are only numbers.
- __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
- __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
- }
+ if (static_operands_type_.IsNumber() && FLAG_debug_code) {
+ // Assert at runtime that inputs are only numbers.
+ __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
+ __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
} else {
FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
}