Commit 5bed1516 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Avoid introducing machine operators during typed lowering.

Introducing machine operators early causes trouble for the typing,
truncation analysis and representation selection, so we should rather
stick to simplified operators instead. Now there's only the for-in case
left, which is not clear how we can handle this in a better way.

Drive-by-fix: Also don't introduce Int32Constant and Word32Shl in
JSTypedLowering, but use NumberConstant and proper NumberShiftLeft
operators instead.

R=jarin@chromium.org
BUG=chromium:630951

Review-Url: https://codereview.chromium.org/2182453002
Cr-Commit-Position: refs/heads/master@{#38008}
parent 37ba8f96
......@@ -173,8 +173,8 @@ Reduction JSIntrinsicLowering::ReduceIsInstanceType(
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value,
effect, if_false),
effect, if_false);
Node* vfalse = graph()->NewNode(machine()->Word32Equal(), efalse,
jsgraph()->Int32Constant(instance_type));
Node* vfalse = graph()->NewNode(simplified()->NumberEqual(), efalse,
jsgraph()->Constant(instance_type));
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
......@@ -386,12 +386,6 @@ JSOperatorBuilder* JSIntrinsicLowering::javascript() const {
return jsgraph_->javascript();
}
MachineOperatorBuilder* JSIntrinsicLowering::machine() const {
return jsgraph()->machine();
}
SimplifiedOperatorBuilder* JSIntrinsicLowering::simplified() const {
return jsgraph()->simplified();
}
......
......@@ -21,7 +21,6 @@ namespace compiler {
class CommonOperatorBuilder;
class JSOperatorBuilder;
class JSGraph;
class MachineOperatorBuilder;
class SimplifiedOperatorBuilder;
......@@ -74,7 +73,6 @@ class JSIntrinsicLowering final : public AdvancedReducer {
Isolate* isolate() const;
CommonOperatorBuilder* common() const;
JSOperatorBuilder* javascript() const;
MachineOperatorBuilder* machine() const;
SimplifiedOperatorBuilder* simplified() const;
DeoptimizationMode mode() const { return mode_; }
......
......@@ -219,7 +219,6 @@ class JSBinopReduction final {
Graph* graph() const { return lowering_->graph(); }
JSGraph* jsgraph() { return lowering_->jsgraph(); }
JSOperatorBuilder* javascript() { return lowering_->javascript(); }
MachineOperatorBuilder* machine() { return lowering_->machine(); }
CommonOperatorBuilder* common() { return jsgraph()->common(); }
Zone* zone() const { return graph()->zone(); }
......@@ -1019,77 +1018,55 @@ Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
if (!receiver_type->Is(Type::Receiver())) {
// TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
if (receiver_type->Maybe(Type::NullOrUndefined()) &&
NodeProperties::IsExceptionalCall(node)) {
// ToObject throws for null or undefined inputs.
return NoChange();
}
if (receiver_type->Is(Type::Receiver())) {
ReplaceWithValue(node, receiver, effect, control);
return Replace(receiver);
}
// Check whether {receiver} is a Smi.
Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
Node* branch0 =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
Node* etrue0 = effect;
Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
Node* efalse0 = effect;
// Determine the instance type of {receiver}.
Node* receiver_map = efalse0 =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
receiver, efalse0, if_false0);
Node* receiver_instance_type = efalse0 = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
receiver_map, efalse0, if_false0);
// Check whether {receiver} is a spec object.
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
Node* check1 =
graph()->NewNode(machine()->Uint32LessThanOrEqual(),
jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
receiver_instance_type);
Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
check1, if_false0);
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
Node* etrue1 = efalse0;
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* efalse1 = efalse0;
// TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
if (receiver_type->Maybe(Type::NullOrUndefined()) &&
NodeProperties::IsExceptionalCall(node)) {
// ToObject throws for null or undefined inputs.
return NoChange();
}
// Convert {receiver} using the ToObjectStub.
Node* if_convert =
graph()->NewNode(common()->Merge(2), if_true0, if_false1);
Node* econvert =
graph()->NewNode(common()->EffectPhi(2), etrue0, efalse1, if_convert);
Node* rconvert;
{
Callable callable = CodeFactory::ToObject(isolate());
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, node->op()->properties());
rconvert = econvert = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
receiver, context, frame_state, econvert, if_convert);
}
// Check whether {receiver} is a spec object.
Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), receiver);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
// The {receiver} is already a spec object.
Node* if_done = if_true1;
Node* edone = etrue1;
Node* rdone = receiver;
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* rtrue = receiver;
control = graph()->NewNode(common()->Merge(2), if_convert, if_done);
effect = graph()->NewNode(common()->EffectPhi(2), econvert, edone, control);
receiver =
graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
rconvert, rdone, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
Node* rfalse;
{
// Convert {receiver} using the ToObjectStub.
Callable callable = CodeFactory::ToObject(isolate());
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0,
CallDescriptor::kNeedsFrameState, node->op()->properties());
rfalse = efalse = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
receiver, context, frame_state, efalse, if_false);
if_false = graph()->NewNode(common()->IfSuccess(), rfalse);
}
ReplaceWithValue(node, receiver, effect, control);
return Changed(receiver);
}
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
// Morph the {node} into an appropriate Phi.
ReplaceWithValue(node, node, effect, control);
node->ReplaceInput(0, rtrue);
node->ReplaceInput(1, rfalse);
node->ReplaceInput(2, control);
node->TrimInputCount(3);
NodeProperties::ChangeOp(node,
common()->Phi(MachineRepresentation::kTagged, 2));
return Changed(node);
}
Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
......@@ -1144,7 +1121,10 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
return Replace(load);
}
// Compute byte offset.
Node* offset = Word32Shl(key, static_cast<int>(k));
Node* offset =
(k == 0) ? key : graph()->NewNode(
simplified()->NumberShiftLeft(), key,
jsgraph()->Constant(static_cast<double>(k)));
Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
offset, length, effect, control);
ReplaceWithValue(node, load, load);
......@@ -1212,7 +1192,10 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
return Changed(node);
}
// Compute byte offset.
Node* offset = Word32Shl(key, static_cast<int>(k));
Node* offset =
(k == 0) ? key : graph()->NewNode(
simplified()->NumberShiftLeft(), key,
jsgraph()->Constant(static_cast<double>(k)));
// Turn into a StoreBuffer operation.
RelaxControls(node);
node->ReplaceInput(0, buffer);
......@@ -1307,10 +1290,10 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
int is_access_check_needed_bit = 1 << Map::kIsAccessCheckNeeded;
Node* is_access_check_needed_num =
graph()->NewNode(simplified()->NumberBitwiseAnd(), map_bit_field,
jsgraph()->Uint32Constant(is_access_check_needed_bit));
jsgraph()->Constant(is_access_check_needed_bit));
Node* is_access_check_needed =
graph()->NewNode(machine()->Word32Equal(), is_access_check_needed_num,
jsgraph()->Uint32Constant(is_access_check_needed_bit));
graph()->NewNode(simplified()->NumberEqual(), is_access_check_needed_num,
jsgraph()->Constant(is_access_check_needed_bit));
Node* branch_is_access_check_needed = graph()->NewNode(
common()->Branch(BranchHint::kFalse), is_access_check_needed, control);
......@@ -1325,8 +1308,9 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
Node* map_instance_type = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
loop_object_map, loop_effect, control);
Node* is_proxy = graph()->NewNode(machine()->Word32Equal(), map_instance_type,
jsgraph()->Uint32Constant(JS_PROXY_TYPE));
Node* is_proxy =
graph()->NewNode(simplified()->NumberEqual(), map_instance_type,
jsgraph()->Constant(JS_PROXY_TYPE));
Node* branch_is_proxy =
graph()->NewNode(common()->Branch(BranchHint::kFalse), is_proxy, control);
Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy);
......@@ -2043,13 +2027,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return NoChange();
}
Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
if (rhs == 0) return lhs;
return graph()->NewNode(machine()->Word32Shl(), lhs,
jsgraph()->Int32Constant(rhs));
}
Node* JSTypedLowering::EmptyFrameState() {
return graph()->NewNode(
common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
......@@ -2077,17 +2054,15 @@ CommonOperatorBuilder* JSTypedLowering::common() const {
return jsgraph()->common();
}
MachineOperatorBuilder* JSTypedLowering::machine() const {
return jsgraph()->machine();
}
SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
return jsgraph()->simplified();
}
MachineOperatorBuilder* JSTypedLowering::machine() const {
return jsgraph()->machine();
}
CompilationDependencies* JSTypedLowering::dependencies() const {
return dependencies_;
}
......
......@@ -24,7 +24,6 @@ namespace compiler {
class CommonOperatorBuilder;
class JSGraph;
class JSOperatorBuilder;
class MachineOperatorBuilder;
class SimplifiedOperatorBuilder;
......@@ -88,8 +87,6 @@ class JSTypedLowering final : public AdvancedReducer {
Reduction ReduceUI32Shift(Node* node, Signedness left_signedness,
const Operator* shift_op);
Node* Word32Shl(Node* const lhs, int32_t const rhs);
Node* EmptyFrameState();
Factory* factory() const;
......
// Copyright 2016 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 foo() {
"use asm";
var o = new Int32Array(64 * 1024);
return () => { o[i1 >> 2] | 0; }
}
assertThrows(foo());
......@@ -29,10 +29,9 @@ class JSIntrinsicLoweringTest : public GraphTest {
~JSIntrinsicLoweringTest() override {}
protected:
Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kNoFlags) {
MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
flags);
Reduction Reduce(Node* node) {
MachineOperatorBuilder machine(zone(),
MachineType::PointerRepresentation());
SimplifiedOperatorBuilder simplified(zone());
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
&machine);
......@@ -87,11 +86,11 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
phi,
IsPhi(
MachineRepresentation::kTagged, IsFalseConstant(),
IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(),
IsLoadField(AccessBuilder::ForMap(), input,
effect, CaptureEq(&if_false)),
effect, _),
IsInt32Constant(JS_ARRAY_TYPE)),
IsNumberConstant(JS_ARRAY_TYPE)),
IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsObjectIsSmi(input), control))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
......@@ -118,11 +117,11 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) {
phi,
IsPhi(
MachineRepresentation::kTagged, IsFalseConstant(),
IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(),
IsLoadField(AccessBuilder::ForMap(), input,
effect, CaptureEq(&if_false)),
effect, _),
IsInt32Constant(JS_TYPED_ARRAY_TYPE)),
IsNumberConstant(JS_TYPED_ARRAY_TYPE)),
IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsObjectIsSmi(input), control))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
......@@ -149,11 +148,11 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsRegExp) {
phi,
IsPhi(
MachineRepresentation::kTagged, IsFalseConstant(),
IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(),
IsLoadField(AccessBuilder::ForMap(), input,
effect, CaptureEq(&if_false)),
effect, _),
IsInt32Constant(JS_REGEXP_TYPE)),
IsNumberConstant(JS_REGEXP_TYPE)),
IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsObjectIsSmi(input), control))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
......
......@@ -619,7 +619,8 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
Matcher<Node*> offset_matcher =
element_size == 1
? key
: IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
: IsNumberShiftLeft(key,
IsNumberConstant(WhichPowerOf2(element_size)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
......@@ -700,7 +701,8 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
Matcher<Node*> offset_matcher =
element_size == 1
? key
: IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
: IsNumberShiftLeft(
key, IsNumberConstant(WhichPowerOf2(element_size)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
......@@ -747,7 +749,8 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
Matcher<Node*> offset_matcher =
element_size == 1
? key
: IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
: IsNumberShiftLeft(
key, IsNumberConstant(WhichPowerOf2(element_size)));
Matcher<Node*> value_matcher =
IsToNumber(value, context, checkpoint, control);
......
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