Commit 7709e41a authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Try hard(er) to use smi representation for float64 values.

Previously ChangeLowering would always box float64 values when going to
tagged representation, but that introduces a lot of deoptimizer loops
and polymorphism into TurboFan, which is unfortunate and unnecessary.

This adds some logic to ChangeFloat64ToTagged to try harder to create a
Smi when going from Float64 to Tagged, instead of always allocating a
HeapNumber.  This might need some additional tweaking, but at least it
makes it possible to start comparing TurboFan and Crankshaft for some
regular JavaScript.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1420913003

Cr-Commit-Position: refs/heads/master@{#31609}
parent 424ae377
......@@ -151,7 +151,78 @@ Reduction ChangeLowering::ChangeBoolToBit(Node* value) {
Reduction ChangeLowering::ChangeFloat64ToTagged(Node* value, Node* control) {
return Replace(AllocateHeapNumberWithValue(value, control));
Type* const value_type = NodeProperties::GetType(value);
Node* const value32 = graph()->NewNode(
machine()->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value);
// TODO(bmeurer): This fast case must be disabled until we kill the asm.js
// support in the generic JavaScript pipeline, because LoadBuffer is lying
// about its result.
// if (value_type->Is(Type::Signed32())) {
// return ChangeInt32ToTagged(value32, control);
// }
Node* check_same = graph()->NewNode(
machine()->Float64Equal(), value,
graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
Node* branch_same = graph()->NewNode(common()->Branch(), check_same, control);
Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_same);
Node* vsmi;
Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same);
Node* vbox;
// We only need to check for -0 if the {value} can potentially contain -0.
if (value_type->Maybe(Type::MinusZero())) {
Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
jsgraph()->Int32Constant(0));
Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
check_zero, if_smi);
Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
// In case of 0, we need to check the high bits for the IEEE -0 pattern.
Node* check_negative = graph()->NewNode(
machine()->Int32LessThan(),
graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
jsgraph()->Int32Constant(0));
Node* branch_negative = graph()->NewNode(
common()->Branch(BranchHint::kFalse), check_negative, if_zero);
Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative);
Node* if_notnegative =
graph()->NewNode(common()->IfFalse(), branch_negative);
// We need to create a box for negative 0.
if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative);
if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative);
}
// On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
// machines we need to deal with potential overflow and fallback to boxing.
if (machine()->Is64() || value_type->Is(Type::SignedSmall())) {
vsmi = ChangeInt32ToSmi(value32);
} else {
Node* smi_tag =
graph()->NewNode(machine()->Int32AddWithOverflow(), value32, value32);
Node* check_ovf = graph()->NewNode(common()->Projection(1), smi_tag);
Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse),
check_ovf, if_smi);
Node* if_ovf = graph()->NewNode(common()->IfTrue(), branch_ovf);
if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box);
if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf);
vsmi = graph()->NewNode(common()->Projection(0), smi_tag);
}
// Allocate the box for the {value}.
vbox = AllocateHeapNumberWithValue(value, if_box);
control = graph()->NewNode(common()->Merge(2), if_smi, if_box);
value =
graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vsmi, vbox, control);
return Replace(value);
}
......
// 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
function f() {
var a = new Array(100000);
var i = 0;
while (!%HasFastDoubleElements(a)) {
a[i] = i;
i += 0.1;
}
a[1] = 1.5;
}
f();
%OptimizeFunctionOnNextCall(f);
f();
......@@ -31,8 +31,8 @@ function get_double_array() {
var a = new Array(100000);
var i = 0;
while (!%HasFastDoubleElements(a)) {
a[i] = i;
i += 0.5;
a[i] = i + 0.1;
i += 1;
}
assertTrue(%HasFastDoubleElements(a));
a.length = 1;
......
......@@ -11,7 +11,7 @@ function ToHeapNumber(i) {
}
for (var i = 0; i < 3; i++) ToHeapNumber(i);
%OptimizeFunctionOnNextCall(ToHeapNumber);
assertFalse(%IsSmi(ToHeapNumber(1)));
ToHeapNumber(1);
function Fail(a, i, v) {
a[i] = v;
......
......@@ -121,25 +121,6 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
Node* value = Parameter(Type::Number());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeFloat64ToTagged(), value));
ASSERT_TRUE(r.Changed());
Capture<Node*> heap_number;
EXPECT_THAT(
r.replacement(),
IsFinishRegion(
AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(IsBeginRegion(graph()->start()),
graph()->start())),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
value, CaptureEq(&heap_number), graph()->start())));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
Node* value = Parameter(Type::SignedSmall());
Reduction r =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment