From 14409abc22bcec02d7613a3e2533b4e61bb95542 Mon Sep 17 00:00:00 2001 From: Benedikt Meurer Date: Fri, 12 Dec 2014 11:45:18 +0100 Subject: [PATCH] [turbofan] Quickfix for invalid number truncation of typed array loads. TEST=mjsunit/compiler/regress-int32array-outofbounds-nan R=jarin@chromium.org Review URL: https://codereview.chromium.org/803483002 Cr-Commit-Position: refs/heads/master@{#25793} --- src/compiler/simplified-lowering.cc | 37 ++++++++++++++++++---- .../compiler/regress-int32array-outofbounds-nan.js | 17 ++++++++++ 2 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 test/mjsunit/compiler/regress-int32array-outofbounds-nan.js diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 3688fc0..b86ffba 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -4,6 +4,8 @@ #include "src/compiler/simplified-lowering.h" +#include + #include "src/base/bits.h" #include "src/code-factory.h" #include "src/compiler/common-operator.h" @@ -764,8 +766,20 @@ class RepresentationSelector { ProcessRemainingInputs(node, 3); // Tagged overrides everything if we have to do a typed array bounds // check, because we may need to return undefined then. - MachineType output_type = - (use & kRepTagged) ? kMachAnyTagged : access.machine_type(); + MachineType output_type; + if (use & kRepTagged) { + output_type = kMachAnyTagged; + } else if (use & kRepFloat64) { + if (access.machine_type() & kRepFloat32) { + output_type = access.machine_type(); + } else { + output_type = kMachFloat64; + } + } else if (use & kRepFloat32) { + output_type = kMachFloat32; + } else { + output_type = access.machine_type(); + } SetOutput(node, output_type); if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); break; @@ -1130,7 +1144,7 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type, DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode()); DCHECK_NE(kMachNone, RepresentationOf(output_type)); MachineType const type = BufferAccessOf(node->op()).machine_type(); - if (output_type & kRepTagged) { + if (output_type != type) { Node* const buffer = node->InputAt(0); Node* const offset = node->InputAt(1); Node* const length = node->InputAt(2); @@ -1144,11 +1158,22 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type, Node* if_true = graph()->NewNode(common()->IfTrue(), branch); Node* etrue = graph()->NewNode(machine()->Load(type), buffer, offset, effect, if_true); - Node* vtrue = changer->GetTaggedRepresentationFor(etrue, type); + Node* vtrue = changer->GetRepresentationFor(etrue, type, output_type); Node* if_false = graph()->NewNode(common()->IfFalse(), branch); - Node* vfalse = jsgraph()->UndefinedConstant(); Node* efalse = effect; + Node* vfalse; + if (output_type & kRepTagged) { + vfalse = jsgraph()->UndefinedConstant(); + } else if (output_type & kRepFloat64) { + vfalse = + jsgraph()->Float64Constant(std::numeric_limits::quiet_NaN()); + } else if (output_type & kRepFloat32) { + vfalse = + jsgraph()->Float32Constant(std::numeric_limits::quiet_NaN()); + } else { + vfalse = jsgraph()->Int32Constant(0); + } Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); @@ -1157,7 +1182,7 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type, NodeProperties::ReplaceWithValue(node, node, ephi); // Turn the {node} into a Phi. - node->set_op(common()->Phi(kMachAnyTagged, 2)); + node->set_op(common()->Phi(output_type, 2)); node->ReplaceInput(0, vtrue); node->ReplaceInput(1, vfalse); node->ReplaceInput(2, merge); diff --git a/test/mjsunit/compiler/regress-int32array-outofbounds-nan.js b/test/mjsunit/compiler/regress-int32array-outofbounds-nan.js new file mode 100644 index 0000000..2eba2a4 --- /dev/null +++ b/test/mjsunit/compiler/regress-int32array-outofbounds-nan.js @@ -0,0 +1,17 @@ +// 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. + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM32 = new stdlib.Int32Array(heap); + function foo(i) { + i = i|0; + return +MEM32[i >> 2]; + } + return {foo: foo}; +} + +var foo = Module(this, {}, new ArrayBuffer(4)).foo; +assertEquals(NaN, foo(-4)); +assertEquals(NaN, foo(4)); -- 2.7.4