From: jkummerow Date: Wed, 8 Jul 2015 10:20:23 +0000 (-0700) Subject: [x64] Fix handling of Smi constants in LSubI and LBitI X-Git-Tag: upstream/4.7.83~1511 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5379d8bc36b3388df4f5a6f7e0a86168f1a5ff0e;p=platform%2Fupstream%2Fv8.git [x64] Fix handling of Smi constants in LSubI and LBitI Smi immediates are not supported, so instructions with Smi representations need their constants in a register. LAddI has already been doing this. The manifestation of the bug was that an operation would compute 0 instead of the correct result. BUG=chromium:478612 LOG=y R=verwaest@chromium.org Review URL: https://codereview.chromium.org/1224623017 Cr-Commit-Position: refs/heads/master@{#29529} --- diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 8f3750552..3c150e21c 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1307,7 +1307,13 @@ LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32)); LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); - LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); + LOperand* right; + if (SmiValuesAre32Bits() && instr->representation().IsSmi()) { + // We don't support tagged immediates, so we request it in a register. + right = UseRegisterAtStart(instr->BetterRightOperand()); + } else { + right = UseOrConstantAtStart(instr->BetterRightOperand()); + } return DefineSameAsFirst(new(zone()) LBitI(left, right)); } else { return DoArithmeticT(instr->op(), instr); @@ -1549,7 +1555,13 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) { DCHECK(instr->left()->representation().Equals(instr->representation())); DCHECK(instr->right()->representation().Equals(instr->representation())); LOperand* left = UseRegisterAtStart(instr->left()); - LOperand* right = UseOrConstantAtStart(instr->right()); + LOperand* right; + if (SmiValuesAre32Bits() && instr->representation().IsSmi()) { + // We don't support tagged immediates, so we request it in a register. + right = UseRegisterAtStart(instr->right()); + } else { + right = UseOrConstantAtStart(instr->right()); + } LSubI* sub = new(zone()) LSubI(left, right); LInstruction* result = DefineSameAsFirst(sub); if (instr->CheckFlag(HValue::kCanOverflow)) { diff --git a/test/mjsunit/regress/regress-crbug-478612.js b/test/mjsunit/regress/regress-crbug-478612.js new file mode 100644 index 000000000..3419722cd --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-478612.js @@ -0,0 +1,52 @@ +// Copyright 2015 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 + +// This is used to force binary operations below to have tagged representation. +var z = {valueOf: function() { return 3; }}; + + +function f() { + var y = -2; + return (1 & z) - y++; +} + +assertEquals(3, f()); +assertEquals(3, f()); +%OptimizeFunctionOnNextCall(f); +assertEquals(3, f()); + + +function g() { + var y = 2; + return (1 & z) | y++; +} + +assertEquals(3, g()); +assertEquals(3, g()); +%OptimizeFunctionOnNextCall(g); +assertEquals(3, g()); + + +function h() { + var y = 3; + return (3 & z) & y++; +} + +assertEquals(3, h()); +assertEquals(3, h()); +%OptimizeFunctionOnNextCall(h); +assertEquals(3, h()); + + +function i() { + var y = 2; + return (1 & z) ^ y++; +} + +assertEquals(3, i()); +assertEquals(3, i()); +%OptimizeFunctionOnNextCall(i); +assertEquals(3, i());