Merge V8 5.2.361.47 DO NOT MERGE
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
FPIIM-449
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
index 88931f5..a76d3e2 100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -6,8 +6,10 @@
#include <limits>
+#include "src/address-map.h"
#include "src/base/bits.h"
#include "src/code-factory.h"
+#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/diamond.h"
#include "src/compiler/linkage.h"
@@ -17,6 +19,7 @@
#include "src/compiler/representation-change.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/source-position.h"
+#include "src/conversions-inl.h"
#include "src/objects.h"
#include "src/type-cache.h"
@@ -84,10 +87,10 @@
static UseInfo Bool() {
return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
}
- static UseInfo Float32() {
+ static UseInfo TruncatingFloat32() {
return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
}
- static UseInfo Float64() {
+ static UseInfo TruncatingFloat64() {
return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
}
static UseInfo PointerInt() {
@@ -122,15 +125,15 @@
case MachineRepresentation::kTagged:
return UseInfo::AnyTagged();
case MachineRepresentation::kFloat64:
- return UseInfo::Float64();
+ return UseInfo::TruncatingFloat64();
case MachineRepresentation::kFloat32:
- return UseInfo::Float32();
+ return UseInfo::TruncatingFloat32();
case MachineRepresentation::kWord64:
- return UseInfo::TruncatingWord64();
+ return UseInfo::TruncatingWord64();
case MachineRepresentation::kWord8:
case MachineRepresentation::kWord16:
case MachineRepresentation::kWord32:
- return UseInfo::TruncatingWord32();
+ return UseInfo::TruncatingWord32();
case MachineRepresentation::kBit:
return UseInfo::Bool();
case MachineRepresentation::kSimd128: // Fall through.
@@ -511,7 +514,8 @@
// Helpers for specific types of binops.
void VisitFloat64Binop(Node* node) {
- VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ VisitBinop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kFloat64);
}
void VisitInt32Binop(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(),
@@ -534,7 +538,7 @@
MachineRepresentation::kWord64);
}
void VisitFloat64Cmp(Node* node) {
- VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kBit);
+ VisitBinop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kBit);
}
void VisitInt32Cmp(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
@@ -563,6 +567,8 @@
return MachineRepresentation::kBit;
} else if (type->Is(Type::Number())) {
return MachineRepresentation::kFloat64;
+ } else if (use.TruncatesToFloat64()) {
+ return MachineRepresentation::kFloat64;
} else if (type->Is(Type::Internal())) {
// We mark (u)int64 as Type::Internal.
// TODO(jarin) This is a workaround for our lack of (u)int64
@@ -630,7 +636,7 @@
}
void VisitCall(Node* node, SimplifiedLowering* lowering) {
- const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op());
+ const CallDescriptor* desc = CallDescriptorOf(node->op());
const MachineSignature* sig = desc->GetMachineSignature();
int params = static_cast<int>(sig->parameter_count());
// Propagate representation information from call descriptor.
@@ -705,6 +711,71 @@
return changer_->Float64OperatorFor(node->opcode());
}
+ WriteBarrierKind WriteBarrierKindFor(
+ BaseTaggedness base_taggedness,
+ MachineRepresentation field_representation, Type* field_type,
+ Node* value) {
+ if (base_taggedness == kTaggedBase &&
+ field_representation == MachineRepresentation::kTagged) {
+ Type* value_type = NodeProperties::GetType(value);
+ if (field_type->Is(Type::TaggedSigned()) ||
+ value_type->Is(Type::TaggedSigned())) {
+ // Write barriers are only for stores of heap objects.
+ return kNoWriteBarrier;
+ }
+ if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
+ value_type->Is(Type::BooleanOrNullOrUndefined())) {
+ // Write barriers are not necessary when storing true, false, null or
+ // undefined, because these special oddballs are always in the root set.
+ return kNoWriteBarrier;
+ }
+ if (value_type->IsConstant() &&
+ value_type->AsConstant()->Value()->IsHeapObject()) {
+ Handle<HeapObject> value_object =
+ Handle<HeapObject>::cast(value_type->AsConstant()->Value());
+ RootIndexMap root_index_map(jsgraph_->isolate());
+ int root_index = root_index_map.Lookup(*value_object);
+ if (root_index != RootIndexMap::kInvalidRootIndex &&
+ jsgraph_->isolate()->heap()->RootIsImmortalImmovable(root_index)) {
+ // Write barriers are unnecessary for immortal immovable roots.
+ return kNoWriteBarrier;
+ }
+ if (value_object->IsMap()) {
+ // Write barriers for storing maps are cheaper.
+ return kMapWriteBarrier;
+ }
+ }
+ if (field_type->Is(Type::TaggedPointer()) ||
+ value_type->Is(Type::TaggedPointer())) {
+ // Write barriers for heap objects are cheaper.
+ return kPointerWriteBarrier;
+ }
+ NumberMatcher m(value);
+ if (m.HasValue()) {
+ if (IsSmiDouble(m.Value())) {
+ // Storing a smi doesn't need a write barrier.
+ return kNoWriteBarrier;
+ }
+ // The NumberConstant will be represented as HeapNumber.
+ return kPointerWriteBarrier;
+ }
+ return kFullWriteBarrier;
+ }
+ return kNoWriteBarrier;
+ }
+
+ WriteBarrierKind WriteBarrierKindFor(
+ BaseTaggedness base_taggedness,
+ MachineRepresentation field_representation, int field_offset,
+ Type* field_type, Node* value) {
+ if (base_taggedness == kTaggedBase &&
+ field_offset == HeapObject::kMapOffset) {
+ return kMapWriteBarrier;
+ }
+ return WriteBarrierKindFor(base_taggedness, field_representation,
+ field_type, value);
+ }
+
// Dispatching routine for visiting the node {node} with the usage {use}.
// Depending on the operator, propagate new usage info to the inputs.
void VisitNode(Node* node, Truncation truncation,
@@ -758,19 +829,23 @@
case IrOpcode::kCall:
return VisitCall(node, lowering);
-//------------------------------------------------------------------
-// JavaScript operators.
-//------------------------------------------------------------------
-// For now, we assume that all JS operators were too complex to lower
-// to Simplified and that they will always require tagged value inputs
-// and produce tagged value outputs.
-// TODO(turbofan): it might be possible to lower some JSOperators here,
-// but that responsibility really lies in the typed lowering phase.
-#define DEFINE_JS_CASE(x) case IrOpcode::k##x:
- JS_OP_LIST(DEFINE_JS_CASE)
-#undef DEFINE_JS_CASE
+ //------------------------------------------------------------------
+ // JavaScript operators.
+ //------------------------------------------------------------------
+ case IrOpcode::kJSToNumber: {
VisitInputs(node);
- return SetOutput(node, MachineRepresentation::kTagged);
+ // TODO(bmeurer): Optimize somewhat based on input type?
+ if (truncation.TruncatesToWord32()) {
+ SetOutput(node, MachineRepresentation::kWord32);
+ if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
+ } else if (truncation.TruncatesToFloat64()) {
+ SetOutput(node, MachineRepresentation::kFloat64);
+ if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
+ } else {
+ SetOutput(node, MachineRepresentation::kTagged);
+ }
+ break;
+ }
//------------------------------------------------------------------
// Simplified operators.
@@ -962,35 +1037,39 @@
}
break;
}
- case IrOpcode::kNumberImul: {
- VisitBinop(node, UseInfo::TruncatingWord32(),
- UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
- if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
- break;
- }
case IrOpcode::kNumberClz32: {
VisitUnop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
break;
}
+ case IrOpcode::kNumberImul: {
+ VisitBinop(node, UseInfo::TruncatingWord32(),
+ UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
+ if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
+ break;
+ }
case IrOpcode::kNumberCeil: {
- VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
break;
}
case IrOpcode::kNumberFloor: {
- VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
break;
}
case IrOpcode::kNumberRound: {
- VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, lowering->Float64Round(node));
break;
}
case IrOpcode::kNumberTrunc: {
- VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
break;
}
@@ -1009,7 +1088,8 @@
break;
}
case IrOpcode::kNumberIsHoleNaN: {
- VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kBit);
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kBit);
if (lower()) {
// NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
// #HoleNaNLower32)
@@ -1023,23 +1103,6 @@
}
break;
}
- case IrOpcode::kPlainPrimitiveToNumber: {
- VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
- if (lower()) {
- // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
- Operator::Properties properties = node->op()->properties();
- Callable callable = CodeFactory::ToNumber(jsgraph_->isolate());
- CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
- CallDescriptor* desc = Linkage::GetStubCallDescriptor(
- jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
- flags, properties);
- node->InsertInput(jsgraph_->zone(), 0,
- jsgraph_->HeapConstant(callable.code()));
- node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
- NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
- }
- break;
- }
case IrOpcode::kReferenceEqual: {
VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
if (lower()) {
@@ -1051,7 +1114,8 @@
VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) {
// StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
- Operator::Properties properties = node->op()->properties();
+ Operator::Properties properties =
+ Operator::kCommutative | Operator::kNoThrow;
Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
@@ -1059,7 +1123,9 @@
flags, properties);
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
- node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
@@ -1068,7 +1134,7 @@
VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) {
// StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
- Operator::Properties properties = node->op()->properties();
+ Operator::Properties properties = Operator::kNoThrow;
Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
@@ -1076,7 +1142,9 @@
flags, properties);
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
- node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
@@ -1086,7 +1154,7 @@
if (lower()) {
// StringLessThanOrEqual(x, y)
// => Call(StringLessThanOrEqualStub, x, y, no-context)
- Operator::Properties properties = node->op()->properties();
+ Operator::Properties properties = Operator::kNoThrow;
Callable callable =
CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
@@ -1095,7 +1163,9 @@
flags, properties);
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
- node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
@@ -1104,7 +1174,7 @@
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) {
// StringToNumber(x) => Call(StringToNumberStub, x, no-context)
- Operator::Properties properties = node->op()->properties();
+ Operator::Properties properties = Operator::kNoThrow;
Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
@@ -1113,12 +1183,14 @@
node->InsertInput(jsgraph_->zone(), 0,
jsgraph_->HeapConstant(callable.code()));
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
+ node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
}
break;
}
case IrOpcode::kAllocate: {
- ProcessInput(node, 0, UseInfo::AnyTagged());
+ ProcessInput(node, 0, UseInfo::TruncatingWord32());
ProcessRemainingInputs(node, 1);
SetOutput(node, MachineRepresentation::kTagged);
break;
@@ -1137,6 +1209,16 @@
access.machine_type.representation()));
ProcessRemainingInputs(node, 2);
SetOutput(node, MachineRepresentation::kNone);
+ if (lower()) {
+ WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
+ access.base_is_tagged, access.machine_type.representation(),
+ access.offset, access.type, node->InputAt(1));
+ if (write_barrier_kind < access.write_barrier_kind) {
+ access.write_barrier_kind = write_barrier_kind;
+ NodeProperties::ChangeOp(
+ node, jsgraph_->simplified()->StoreField(access));
+ }
+ }
break;
}
case IrOpcode::kLoadBuffer: {
@@ -1160,18 +1242,10 @@
MachineRepresentation::kFloat32) {
output = access.machine_type().representation();
} else {
- if (access.machine_type().representation() !=
- MachineRepresentation::kFloat64) {
- // TODO(bmeurer): See comment on abort_compilation_.
- if (lower()) lowering->abort_compilation_ = true;
- }
output = MachineRepresentation::kFloat64;
}
}
} else {
- // TODO(bmeurer): See comment on abort_compilation_.
- if (lower()) lowering->abort_compilation_ = true;
-
// If undefined is not truncated away, we need to have the tagged
// representation.
output = MachineRepresentation::kTagged;
@@ -1210,11 +1284,23 @@
access.machine_type.representation())); // value
ProcessRemainingInputs(node, 3);
SetOutput(node, MachineRepresentation::kNone);
+ if (lower()) {
+ WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
+ access.base_is_tagged, access.machine_type.representation(),
+ access.type, node->InputAt(2));
+ if (write_barrier_kind < access.write_barrier_kind) {
+ access.write_barrier_kind = write_barrier_kind;
+ NodeProperties::ChangeOp(
+ node, jsgraph_->simplified()->StoreElement(access));
+ }
+ }
break;
}
+ case IrOpcode::kObjectIsCallable:
case IrOpcode::kObjectIsNumber:
case IrOpcode::kObjectIsReceiver:
case IrOpcode::kObjectIsSmi:
+ case IrOpcode::kObjectIsString:
case IrOpcode::kObjectIsUndetectable: {
ProcessInput(node, 0, UseInfo::AnyTagged());
SetOutput(node, MachineRepresentation::kBit);
@@ -1323,14 +1409,15 @@
return VisitUnop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord64);
case IrOpcode::kTruncateFloat64ToFloat32:
- return VisitUnop(node, UseInfo::Float64(),
+ return VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat32);
- case IrOpcode::kTruncateFloat64ToInt32:
- return VisitUnop(node, UseInfo::Float64(),
+ case IrOpcode::kTruncateFloat64ToWord32:
+ return VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kWord32);
case IrOpcode::kChangeFloat32ToFloat64:
- return VisitUnop(node, UseInfo::Float32(),
+ UNREACHABLE();
+ return VisitUnop(node, UseInfo::TruncatingFloat32(),
MachineRepresentation::kFloat64);
case IrOpcode::kChangeInt32ToFloat64:
return VisitUnop(node, UseInfo::TruncatingWord32(),
@@ -1351,7 +1438,7 @@
case IrOpcode::kFloat64RoundTruncate:
case IrOpcode::kFloat64RoundTiesAway:
case IrOpcode::kFloat64RoundUp:
- return VisitUnop(node, UseInfo::Float64(),
+ return VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat64);
case IrOpcode::kFloat64Equal:
case IrOpcode::kFloat64LessThan:
@@ -1359,11 +1446,12 @@
return VisitFloat64Cmp(node);
case IrOpcode::kFloat64ExtractLowWord32:
case IrOpcode::kFloat64ExtractHighWord32:
- return VisitUnop(node, UseInfo::Float64(),
+ return VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kWord32);
case IrOpcode::kFloat64InsertLowWord32:
case IrOpcode::kFloat64InsertHighWord32:
- return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
+ return VisitBinop(node, UseInfo::TruncatingFloat64(),
+ UseInfo::TruncatingWord32(),
MachineRepresentation::kFloat64);
case IrOpcode::kLoadStackPointer:
case IrOpcode::kLoadFramePointer:
@@ -1482,6 +1570,166 @@
selector.Run(this);
}
+void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
+ Node* node, RepresentationSelector* selector) {
+ DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
+ Node* value = node->InputAt(0);
+ Node* context = node->InputAt(1);
+ Node* frame_state = node->InputAt(2);
+ Node* effect = node->InputAt(3);
+ Node* control = node->InputAt(4);
+ Node* throwing;
+
+ Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
+ Node* branch0 =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* etrue0 = effect;
+ Node* vtrue0;
+ {
+ vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
+ vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
+ }
+
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* efalse0 = effect;
+ Node* vfalse0;
+ {
+ throwing = vfalse0 = efalse0 =
+ graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
+ frame_state, efalse0, if_false0);
+ if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
+
+ Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
+ Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* etrue1 = efalse0;
+ Node* vtrue1;
+ {
+ vtrue1 =
+ graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
+ vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
+ }
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* efalse1 = efalse0;
+ Node* vfalse1;
+ {
+ vfalse1 = efalse1 = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
+ efalse1, if_false1);
+ }
+
+ if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ efalse0 =
+ graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
+ vfalse0 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_false0);
+ }
+
+ control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue0, vfalse0, control);
+
+ // Replace effect and control uses appropriately.
+ for (Edge edge : node->use_edges()) {
+ if (NodeProperties::IsControlEdge(edge)) {
+ if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
+ edge.from()->ReplaceUses(control);
+ edge.from()->Kill();
+ } else if (edge.from()->opcode() == IrOpcode::kIfException) {
+ edge.UpdateTo(throwing);
+ } else {
+ UNREACHABLE();
+ }
+ } else if (NodeProperties::IsEffectEdge(edge)) {
+ edge.UpdateTo(effect);
+ }
+ }
+
+ selector->DeferReplacement(node, value);
+}
+
+void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
+ Node* node, RepresentationSelector* selector) {
+ DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
+ Node* value = node->InputAt(0);
+ Node* context = node->InputAt(1);
+ Node* frame_state = node->InputAt(2);
+ Node* effect = node->InputAt(3);
+ Node* control = node->InputAt(4);
+ Node* throwing;
+
+ Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
+ Node* branch0 =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* etrue0 = effect;
+ Node* vtrue0 =
+ graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
+
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* efalse0 = effect;
+ Node* vfalse0;
+ {
+ throwing = vfalse0 = efalse0 =
+ graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
+ frame_state, efalse0, if_false0);
+ if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
+
+ Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
+ Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* etrue1 = efalse0;
+ Node* vtrue1 =
+ graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* efalse1 = efalse0;
+ Node* vfalse1;
+ {
+ vfalse1 = efalse1 = graph()->NewNode(
+ simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
+ efalse1, if_false1);
+ vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
+ }
+
+ if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ efalse0 =
+ graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
+ vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+ vtrue1, vfalse1, if_false0);
+ }
+
+ control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+ vtrue0, vfalse0, control);
+
+ // Replace effect and control uses appropriately.
+ for (Edge edge : node->use_edges()) {
+ if (NodeProperties::IsControlEdge(edge)) {
+ if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
+ edge.from()->ReplaceUses(control);
+ edge.from()->Kill();
+ } else if (edge.from()->opcode() == IrOpcode::kIfException) {
+ edge.UpdateTo(throwing);
+ } else {
+ UNREACHABLE();
+ }
+ } else if (NodeProperties::IsEffectEdge(edge)) {
+ edge.UpdateTo(effect);
+ }
+ }
+
+ selector->DeferReplacement(node, value);
+}
void SimplifiedLowering::DoLoadBuffer(Node* node,
MachineRepresentation output_rep,
@@ -1507,9 +1755,11 @@
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
effect, if_true);
+ Type* element_type =
+ Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
Node* vtrue = changer->GetRepresentationFor(
- etrue, access_type.representation(), NodeProperties::GetType(node),
- output_rep, Truncation::None());
+ etrue, access_type.representation(), element_type, output_rep,
+ Truncation::None());
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
@@ -2200,6 +2450,26 @@
NodeProperties::ChangeOp(node, op);
}
+Node* SimplifiedLowering::ToNumberCode() {
+ if (!to_number_code_.is_set()) {
+ Callable callable = CodeFactory::ToNumber(isolate());
+ to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
+ }
+ return to_number_code_.get();
+}
+
+Operator const* SimplifiedLowering::ToNumberOperator() {
+ if (!to_number_operator_.is_set()) {
+ Callable callable = CodeFactory::ToNumber(isolate());
+ CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ isolate(), graph()->zone(), callable.descriptor(), 0, flags,
+ Operator::kNoProperties);
+ to_number_operator_.set(common()->Call(desc));
+ }
+ return to_number_operator_.get();
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8