| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 4570)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -193,6 +193,34 @@
|
| };
|
|
|
|
|
| +// 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
|
| @@ -6363,6 +6391,16 @@
|
| }
|
|
|
|
|
| +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,
|
| @@ -6492,9 +6530,45 @@
|
|
|
| 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.
|
| @@ -7201,10 +7275,8 @@
|
| // 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.
|
| @@ -9961,12 +10033,10 @@
|
| 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);
|
| }
|
|
|