From 0f71a24f3a433e2b8a425f5a1e62b4ed0a2eb74b Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Thu, 13 Mar 2014 13:57:21 +0000 Subject: [PATCH] Correctly retain argument value when deopting from Math.round on x64. R=jkummerow@chromium.org BUG=351624 LOG=N Review URL: https://codereview.chromium.org/199013002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19896 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/x64/lithium-codegen-x64.cc | 15 +++++++-------- src/x64/lithium-x64.cc | 5 +++-- src/x64/lithium-x64.h | 6 ++++-- test/mjsunit/regress/regress-351624.js | 23 +++++++++++++++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 test/mjsunit/regress/regress-351624.js diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index f350b07d5..11cfa6966 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -3604,10 +3604,11 @@ void LCodeGen::DoMathRound(LMathRound* instr) { const XMMRegister xmm_scratch = double_scratch0(); Register output_reg = ToRegister(instr->result()); XMMRegister input_reg = ToDoubleRegister(instr->value()); + XMMRegister input_temp = ToDoubleRegister(instr->temp()); static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 - Label done, round_to_zero, below_one_half, do_not_compensate, restore; + Label done, round_to_zero, below_one_half; Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; __ movq(kScratchRegister, one_half); __ movq(xmm_scratch, kScratchRegister); @@ -3631,21 +3632,19 @@ void LCodeGen::DoMathRound(LMathRound* instr) { // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then // compare and compensate. - __ movq(kScratchRegister, input_reg); // Back up input_reg. - __ subsd(input_reg, xmm_scratch); - __ cvttsd2si(output_reg, input_reg); + __ movq(input_temp, input_reg); // Do not alter input_reg. + __ subsd(input_temp, xmm_scratch); + __ cvttsd2si(output_reg, input_temp); // Catch minint due to overflow, and to prevent overflow when compensating. __ cmpl(output_reg, Immediate(0x80000000)); __ RecordComment("D2I conversion overflow"); DeoptimizeIf(equal, instr->environment()); __ Cvtlsi2sd(xmm_scratch, output_reg); - __ ucomisd(input_reg, xmm_scratch); - __ j(equal, &restore, Label::kNear); + __ ucomisd(xmm_scratch, input_temp); + __ j(equal, &done, dist); __ subl(output_reg, Immediate(1)); // No overflow because we already ruled out minint. - __ bind(&restore); - __ movq(input_reg, kScratchRegister); // Restore input_reg. __ jmp(&done, dist); __ bind(&round_to_zero); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 625b4f4ce..aad9597f1 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1133,8 +1133,9 @@ LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { - LOperand* input = UseRegisterAtStart(instr->value()); - LMathRound* result = new(zone()) LMathRound(input); + LOperand* input = UseRegister(instr->value()); + LOperand* temp = FixedTemp(xmm4); + LMathRound* result = new(zone()) LMathRound(input, temp); return AssignEnvironment(DefineAsRegister(result)); } diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index e8760723b..8ae131973 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -835,13 +835,15 @@ class LMathFloor V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; -class LMathRound V8_FINAL : public LTemplateInstruction<1, 1, 0> { +class LMathRound V8_FINAL : public LTemplateInstruction<1, 1, 1> { public: - explicit LMathRound(LOperand* value) { + explicit LMathRound(LOperand* value, LOperand* temp) { inputs_[0] = value; + temps_[0] = temp; } LOperand* value() { return inputs_[0]; } + LOperand* temp() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round") DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) diff --git a/test/mjsunit/regress/regress-351624.js b/test/mjsunit/regress/regress-351624.js new file mode 100644 index 000000000..fc3715b65 --- /dev/null +++ b/test/mjsunit/regress/regress-351624.js @@ -0,0 +1,23 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var big = 1e10; +var backup = new Float64Array(1); + +function mult0(val){ + var prod = val * big; + backup[0] = prod; + var rounded = Math.round(prod); + assertEquals(prod, backup[0]); + return rounded; +} + +var count = 5; +for (var i = 0; i < count; i++) { + if (i == count - 1) %OptimizeFunctionOnNextCall(mult0); + var result = mult0(-1); + assertEquals(result, -big); +} -- 2.34.1