summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/instruction-selector.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/instruction-selector.cc')
-rw-r--r--deps/v8/src/compiler/instruction-selector.cc447
1 files changed, 356 insertions, 91 deletions
diff --git a/deps/v8/src/compiler/instruction-selector.cc b/deps/v8/src/compiler/instruction-selector.cc
index b7162fe5dc..ac8e64a58a 100644
--- a/deps/v8/src/compiler/instruction-selector.cc
+++ b/deps/v8/src/compiler/instruction-selector.cc
@@ -87,7 +87,6 @@ void InstructionSelector::SelectInstructions() {
#endif
}
-
void InstructionSelector::StartBlock(RpoNumber rpo) {
if (FLAG_turbo_instruction_scheduling &&
InstructionScheduler::SchedulerSupported()) {
@@ -242,6 +241,20 @@ bool InstructionSelector::CanCover(Node* user, Node* node) const {
return true;
}
+bool InstructionSelector::IsOnlyUserOfNodeInSameBlock(Node* user,
+ Node* node) const {
+ BasicBlock* bb_user = schedule()->block(user);
+ BasicBlock* bb_node = schedule()->block(node);
+ if (bb_user != bb_node) return false;
+ for (Edge const edge : node->use_edges()) {
+ Node* from = edge.from();
+ if ((from != user) && (schedule()->block(from) == bb_user)) {
+ return false;
+ }
+ }
+ return true;
+}
+
int InstructionSelector::GetVirtualRegister(const Node* node) {
DCHECK_NOT_NULL(node);
size_t const id = node->id();
@@ -286,6 +299,9 @@ void InstructionSelector::MarkAsDefined(Node* node) {
bool InstructionSelector::IsUsed(Node* node) const {
DCHECK_NOT_NULL(node);
+ // TODO(bmeurer): This is a terrible monster hack, but we have to make sure
+ // that the Retain is actually emitted, otherwise the GC will mess up.
+ if (node->opcode() == IrOpcode::kRetain) return true;
if (!node->op()->HasProperty(Operator::kEliminatable)) return true;
size_t const id = node->id();
DCHECK_LT(id, used_.size());
@@ -331,11 +347,12 @@ namespace {
enum class FrameStateInputKind { kAny, kStackSlot };
-
InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
- FrameStateInputKind kind) {
+ FrameStateInputKind kind,
+ MachineRepresentation rep) {
switch (input->opcode()) {
case IrOpcode::kInt32Constant:
+ case IrOpcode::kInt64Constant:
case IrOpcode::kNumberConstant:
case IrOpcode::kFloat32Constant:
case IrOpcode::kFloat64Constant:
@@ -345,11 +362,15 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
UNREACHABLE();
break;
default:
- switch (kind) {
- case FrameStateInputKind::kStackSlot:
- return g->UseUniqueSlot(input);
- case FrameStateInputKind::kAny:
- return g->UseAny(input);
+ if (rep == MachineRepresentation::kNone) {
+ return g->TempImmediate(FrameStateDescriptor::kImpossibleValue);
+ } else {
+ switch (kind) {
+ case FrameStateInputKind::kStackSlot:
+ return g->UseUniqueSlot(input);
+ case FrameStateInputKind::kAny:
+ return g->UseAny(input);
+ }
}
}
UNREACHABLE();
@@ -415,7 +436,7 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
break;
}
default: {
- inputs->push_back(OperandForDeopt(g, input, kind));
+ inputs->push_back(OperandForDeopt(g, input, kind, type.representation()));
descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type));
return 1;
}
@@ -561,17 +582,17 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
bool output_is_live = buffer->output_nodes[i] != nullptr ||
i < outputs_needed_by_framestate;
if (output_is_live) {
- MachineType type =
- buffer->descriptor->GetReturnType(static_cast<int>(i));
+ MachineRepresentation rep =
+ buffer->descriptor->GetReturnType(static_cast<int>(i))
+ .representation();
LinkageLocation location =
buffer->descriptor->GetReturnLocation(static_cast<int>(i));
Node* output = buffer->output_nodes[i];
- InstructionOperand op =
- output == nullptr
- ? g.TempLocation(location, type.representation())
- : g.DefineAsLocation(output, location, type.representation());
- MarkAsRepresentation(type.representation(), op);
+ InstructionOperand op = output == nullptr
+ ? g.TempLocation(location)
+ : g.DefineAsLocation(output, location);
+ MarkAsRepresentation(rep, op);
buffer->outputs.push_back(op);
}
@@ -598,8 +619,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
break;
case CallDescriptor::kCallJSFunction:
buffer->instruction_args.push_back(
- g.UseLocation(callee, buffer->descriptor->GetInputLocation(0),
- buffer->descriptor->GetInputType(0).representation()));
+ g.UseLocation(callee, buffer->descriptor->GetInputLocation(0)));
break;
}
DCHECK_EQ(1u, buffer->instruction_args.size());
@@ -618,7 +638,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
// all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame.
if (buffer->descriptor->SupportsTailCalls()) {
- frame_state = NodeProperties::GetFrameStateInput(frame_state, 0);
+ frame_state = NodeProperties::GetFrameStateInput(frame_state);
buffer->frame_state_descriptor =
buffer->frame_state_descriptor->outer_state();
while (buffer->frame_state_descriptor != nullptr &&
@@ -626,15 +646,15 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
FrameStateType::kArgumentsAdaptor ||
buffer->frame_state_descriptor->type() ==
FrameStateType::kTailCallerFunction)) {
- frame_state = NodeProperties::GetFrameStateInput(frame_state, 0);
+ frame_state = NodeProperties::GetFrameStateInput(frame_state);
buffer->frame_state_descriptor =
buffer->frame_state_descriptor->outer_state();
}
}
- InstructionSequence::StateId state_id =
- sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
- buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
+ int const state_id = sequence()->AddDeoptimizationEntry(
+ buffer->frame_state_descriptor, DeoptimizeReason::kNoReason);
+ buffer->instruction_args.push_back(g.TempImmediate(state_id));
StateObjectDeduplicator deduplicator(instruction_zone());
@@ -666,9 +686,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
location = LinkageLocation::ConvertToTailCallerLocation(
location, stack_param_delta);
}
- InstructionOperand op =
- g.UseLocation(*iter, location,
- buffer->descriptor->GetInputType(index).representation());
+ InstructionOperand op = g.UseLocation(*iter, location);
if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) {
int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1;
if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
@@ -707,6 +725,7 @@ void InstructionSelector::VisitBlock(BasicBlock* block) {
int effect_level = 0;
for (Node* const node : *block) {
if (node->opcode() == IrOpcode::kStore ||
+ node->opcode() == IrOpcode::kUnalignedStore ||
node->opcode() == IrOpcode::kCheckedStore ||
node->opcode() == IrOpcode::kCall) {
++effect_level;
@@ -823,9 +842,9 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
return VisitReturn(input);
}
case BasicBlock::kDeoptimize: {
- DeoptimizeKind kind = DeoptimizeKindOf(input->op());
+ DeoptimizeParameters p = DeoptimizeParametersOf(input->op());
Node* value = input->InputAt(0);
- return VisitDeoptimize(kind, value);
+ return VisitDeoptimize(p.kind(), p.reason(), value);
}
case BasicBlock::kThrow:
DCHECK_EQ(IrOpcode::kThrow, input->opcode());
@@ -865,8 +884,6 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsReference(node), VisitIfException(node);
case IrOpcode::kFinishRegion:
return MarkAsReference(node), VisitFinishRegion(node);
- case IrOpcode::kGuard:
- return MarkAsReference(node), VisitGuard(node);
case IrOpcode::kParameter: {
MachineType type =
linkage()->GetParameterType(ParameterIndexOf(node->op()));
@@ -877,6 +894,7 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsReference(node), VisitOsrValue(node);
case IrOpcode::kPhi: {
MachineRepresentation rep = PhiRepresentationOf(node->op());
+ if (rep == MachineRepresentation::kNone) return;
MarkAsRepresentation(rep, node);
return VisitPhi(node);
}
@@ -885,6 +903,8 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kInt32Constant:
case IrOpcode::kInt64Constant:
case IrOpcode::kExternalConstant:
+ case IrOpcode::kRelocatableInt32Constant:
+ case IrOpcode::kRelocatableInt64Constant:
return VisitConstant(node);
case IrOpcode::kFloat32Constant:
return MarkAsFloat32(node), VisitConstant(node);
@@ -907,6 +927,15 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kStateValues:
case IrOpcode::kObjectState:
return;
+ case IrOpcode::kDebugBreak:
+ VisitDebugBreak(node);
+ return;
+ case IrOpcode::kComment:
+ VisitComment(node);
+ return;
+ case IrOpcode::kRetain:
+ VisitRetain(node);
+ return;
case IrOpcode::kLoad: {
LoadRepresentation type = LoadRepresentationOf(node->op());
MarkAsRepresentation(type.representation(), node);
@@ -936,6 +965,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord32(node), VisitWord32Ctz(node);
case IrOpcode::kWord32ReverseBits:
return MarkAsWord32(node), VisitWord32ReverseBits(node);
+ case IrOpcode::kWord32ReverseBytes:
+ return MarkAsWord32(node), VisitWord32ReverseBytes(node);
case IrOpcode::kWord32Popcnt:
return MarkAsWord32(node), VisitWord32Popcnt(node);
case IrOpcode::kWord64Popcnt:
@@ -960,6 +991,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord64(node), VisitWord64Ctz(node);
case IrOpcode::kWord64ReverseBits:
return MarkAsWord64(node), VisitWord64ReverseBits(node);
+ case IrOpcode::kWord64ReverseBytes:
+ return MarkAsWord64(node), VisitWord64ReverseBytes(node);
case IrOpcode::kWord64Equal:
return VisitWord64Equal(node);
case IrOpcode::kInt32Add:
@@ -972,6 +1005,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitInt32SubWithOverflow(node);
case IrOpcode::kInt32Mul:
return MarkAsWord32(node), VisitInt32Mul(node);
+ case IrOpcode::kInt32MulWithOverflow:
+ return MarkAsWord32(node), VisitInt32MulWithOverflow(node);
case IrOpcode::kInt32MulHigh:
return VisitInt32MulHigh(node);
case IrOpcode::kInt32Div:
@@ -1018,6 +1053,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitUint64LessThanOrEqual(node);
case IrOpcode::kUint64Mod:
return MarkAsWord64(node), VisitUint64Mod(node);
+ case IrOpcode::kBitcastWordToTagged:
+ return MarkAsReference(node), VisitBitcastWordToTagged(node);
case IrOpcode::kChangeFloat32ToFloat64:
return MarkAsFloat64(node), VisitChangeFloat32ToFloat64(node);
case IrOpcode::kChangeInt32ToFloat64:
@@ -1028,6 +1065,26 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
case IrOpcode::kChangeFloat64ToUint32:
return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
+ case IrOpcode::kImpossibleToWord32:
+ return MarkAsWord32(node), VisitImpossibleToWord32(node);
+ case IrOpcode::kImpossibleToWord64:
+ return MarkAsWord64(node), VisitImpossibleToWord64(node);
+ case IrOpcode::kImpossibleToFloat32:
+ return MarkAsFloat32(node), VisitImpossibleToFloat32(node);
+ case IrOpcode::kImpossibleToFloat64:
+ return MarkAsFloat64(node), VisitImpossibleToFloat64(node);
+ case IrOpcode::kImpossibleToTagged:
+ MarkAsRepresentation(MachineType::PointerRepresentation(), node);
+ return VisitImpossibleToTagged(node);
+ case IrOpcode::kImpossibleToBit:
+ return MarkAsWord32(node), VisitImpossibleToBit(node);
+ case IrOpcode::kFloat64SilenceNaN:
+ MarkAsFloat64(node);
+ if (CanProduceSignalingNaN(node->InputAt(0))) {
+ return VisitFloat64SilenceNaN(node);
+ } else {
+ return EmitIdentity(node);
+ }
case IrOpcode::kTruncateFloat64ToUint32:
return MarkAsWord32(node), VisitTruncateFloat64ToUint32(node);
case IrOpcode::kTruncateFloat32ToInt32:
@@ -1048,10 +1105,12 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord64(node), VisitChangeUint32ToUint64(node);
case IrOpcode::kTruncateFloat64ToFloat32:
return MarkAsFloat32(node), VisitTruncateFloat64ToFloat32(node);
- case IrOpcode::kTruncateFloat64ToInt32:
- return MarkAsWord32(node), VisitTruncateFloat64ToInt32(node);
+ case IrOpcode::kTruncateFloat64ToWord32:
+ return MarkAsWord32(node), VisitTruncateFloat64ToWord32(node);
case IrOpcode::kTruncateInt64ToInt32:
return MarkAsWord32(node), VisitTruncateInt64ToInt32(node);
+ case IrOpcode::kRoundFloat64ToInt32:
+ return MarkAsWord32(node), VisitRoundFloat64ToInt32(node);
case IrOpcode::kRoundInt64ToFloat32:
return MarkAsFloat32(node), VisitRoundInt64ToFloat32(node);
case IrOpcode::kRoundInt32ToFloat32:
@@ -1076,14 +1135,12 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat32(node), VisitFloat32Add(node);
case IrOpcode::kFloat32Sub:
return MarkAsFloat32(node), VisitFloat32Sub(node);
+ case IrOpcode::kFloat32Neg:
+ return MarkAsFloat32(node), VisitFloat32Neg(node);
case IrOpcode::kFloat32Mul:
return MarkAsFloat32(node), VisitFloat32Mul(node);
case IrOpcode::kFloat32Div:
return MarkAsFloat32(node), VisitFloat32Div(node);
- case IrOpcode::kFloat32Min:
- return MarkAsFloat32(node), VisitFloat32Min(node);
- case IrOpcode::kFloat32Max:
- return MarkAsFloat32(node), VisitFloat32Max(node);
case IrOpcode::kFloat32Abs:
return MarkAsFloat32(node), VisitFloat32Abs(node);
case IrOpcode::kFloat32Sqrt:
@@ -1094,10 +1151,16 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitFloat32LessThan(node);
case IrOpcode::kFloat32LessThanOrEqual:
return VisitFloat32LessThanOrEqual(node);
+ case IrOpcode::kFloat32Max:
+ return MarkAsFloat32(node), VisitFloat32Max(node);
+ case IrOpcode::kFloat32Min:
+ return MarkAsFloat32(node), VisitFloat32Min(node);
case IrOpcode::kFloat64Add:
return MarkAsFloat64(node), VisitFloat64Add(node);
case IrOpcode::kFloat64Sub:
return MarkAsFloat64(node), VisitFloat64Sub(node);
+ case IrOpcode::kFloat64Neg:
+ return MarkAsFloat64(node), VisitFloat64Neg(node);
case IrOpcode::kFloat64Mul:
return MarkAsFloat64(node), VisitFloat64Mul(node);
case IrOpcode::kFloat64Div:
@@ -1110,8 +1173,50 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64Max(node);
case IrOpcode::kFloat64Abs:
return MarkAsFloat64(node), VisitFloat64Abs(node);
+ case IrOpcode::kFloat64Acos:
+ return MarkAsFloat64(node), VisitFloat64Acos(node);
+ case IrOpcode::kFloat64Acosh:
+ return MarkAsFloat64(node), VisitFloat64Acosh(node);
+ case IrOpcode::kFloat64Asin:
+ return MarkAsFloat64(node), VisitFloat64Asin(node);
+ case IrOpcode::kFloat64Asinh:
+ return MarkAsFloat64(node), VisitFloat64Asinh(node);
+ case IrOpcode::kFloat64Atan:
+ return MarkAsFloat64(node), VisitFloat64Atan(node);
+ case IrOpcode::kFloat64Atanh:
+ return MarkAsFloat64(node), VisitFloat64Atanh(node);
+ case IrOpcode::kFloat64Atan2:
+ return MarkAsFloat64(node), VisitFloat64Atan2(node);
+ case IrOpcode::kFloat64Cbrt:
+ return MarkAsFloat64(node), VisitFloat64Cbrt(node);
+ case IrOpcode::kFloat64Cos:
+ return MarkAsFloat64(node), VisitFloat64Cos(node);
+ case IrOpcode::kFloat64Cosh:
+ return MarkAsFloat64(node), VisitFloat64Cosh(node);
+ case IrOpcode::kFloat64Exp:
+ return MarkAsFloat64(node), VisitFloat64Exp(node);
+ case IrOpcode::kFloat64Expm1:
+ return MarkAsFloat64(node), VisitFloat64Expm1(node);
+ case IrOpcode::kFloat64Log:
+ return MarkAsFloat64(node), VisitFloat64Log(node);
+ case IrOpcode::kFloat64Log1p:
+ return MarkAsFloat64(node), VisitFloat64Log1p(node);
+ case IrOpcode::kFloat64Log10:
+ return MarkAsFloat64(node), VisitFloat64Log10(node);
+ case IrOpcode::kFloat64Log2:
+ return MarkAsFloat64(node), VisitFloat64Log2(node);
+ case IrOpcode::kFloat64Pow:
+ return MarkAsFloat64(node), VisitFloat64Pow(node);
+ case IrOpcode::kFloat64Sin:
+ return MarkAsFloat64(node), VisitFloat64Sin(node);
+ case IrOpcode::kFloat64Sinh:
+ return MarkAsFloat64(node), VisitFloat64Sinh(node);
case IrOpcode::kFloat64Sqrt:
return MarkAsFloat64(node), VisitFloat64Sqrt(node);
+ case IrOpcode::kFloat64Tan:
+ return MarkAsFloat64(node), VisitFloat64Tan(node);
+ case IrOpcode::kFloat64Tanh:
+ return MarkAsFloat64(node), VisitFloat64Tanh(node);
case IrOpcode::kFloat64Equal:
return VisitFloat64Equal(node);
case IrOpcode::kFloat64LessThan:
@@ -1152,6 +1257,14 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitLoadFramePointer(node);
case IrOpcode::kLoadParentFramePointer:
return VisitLoadParentFramePointer(node);
+ case IrOpcode::kUnalignedLoad: {
+ UnalignedLoadRepresentation type =
+ UnalignedLoadRepresentationOf(node->op());
+ MarkAsRepresentation(type.representation(), node);
+ return VisitUnalignedLoad(node);
+ }
+ case IrOpcode::kUnalignedStore:
+ return VisitUnalignedStore(node);
case IrOpcode::kCheckedLoad: {
MachineRepresentation rep =
CheckedLoadRepresentationOf(node->op()).representation();
@@ -1184,6 +1297,16 @@ void InstructionSelector::VisitNode(Node* node) {
MarkAsWord32(NodeProperties::FindProjection(node, 0));
MarkAsWord32(NodeProperties::FindProjection(node, 1));
return VisitWord32PairSar(node);
+ case IrOpcode::kAtomicLoad: {
+ LoadRepresentation type = LoadRepresentationOf(node->op());
+ MarkAsRepresentation(type.representation(), node);
+ return VisitAtomicLoad(node);
+ }
+ case IrOpcode::kAtomicStore:
+ return VisitAtomicStore(node);
+ case IrOpcode::kUnsafePointerAdd:
+ MarkAsRepresentation(MachineType::PointerRepresentation(), node);
+ return VisitUnsafePointerAdd(node);
default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id());
@@ -1191,13 +1314,47 @@ void InstructionSelector::VisitNode(Node* node) {
}
}
+void InstructionSelector::VisitImpossibleToWord32(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0)));
+}
+
+void InstructionSelector::VisitImpossibleToWord64(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchImpossible,
+ g.DefineAsConstant(node, Constant(static_cast<int64_t>(0))));
+}
+
+void InstructionSelector::VisitImpossibleToFloat32(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0.0f)));
+}
+
+void InstructionSelector::VisitImpossibleToFloat64(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0.0)));
+}
+
+void InstructionSelector::VisitImpossibleToBit(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0)));
+}
+
+void InstructionSelector::VisitImpossibleToTagged(Node* node) {
+ OperandGenerator g(this);
+#if V8_TARGET_ARCH_64_BIT
+ Emit(kArchImpossible,
+ g.DefineAsConstant(node, Constant(static_cast<int64_t>(0))));
+#else // V8_TARGET_ARCH_64_BIT
+ Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0)));
+#endif // V8_TARGET_ARCH_64_BIT
+}
void InstructionSelector::VisitLoadStackPointer(Node* node) {
OperandGenerator g(this);
Emit(kArchStackPointer, g.DefineAsRegister(node));
}
-
void InstructionSelector::VisitLoadFramePointer(Node* node) {
OperandGenerator g(this);
Emit(kArchFramePointer, g.DefineAsRegister(node));
@@ -1208,6 +1365,90 @@ void InstructionSelector::VisitLoadParentFramePointer(Node* node) {
Emit(kArchParentFramePointer, g.DefineAsRegister(node));
}
+void InstructionSelector::VisitFloat64Acos(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Acos);
+}
+
+void InstructionSelector::VisitFloat64Acosh(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Acosh);
+}
+
+void InstructionSelector::VisitFloat64Asin(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Asin);
+}
+
+void InstructionSelector::VisitFloat64Asinh(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Asinh);
+}
+
+void InstructionSelector::VisitFloat64Atan(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Atan);
+}
+
+void InstructionSelector::VisitFloat64Atanh(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Atanh);
+}
+
+void InstructionSelector::VisitFloat64Atan2(Node* node) {
+ VisitFloat64Ieee754Binop(node, kIeee754Float64Atan2);
+}
+
+void InstructionSelector::VisitFloat64Cbrt(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Cbrt);
+}
+
+void InstructionSelector::VisitFloat64Cos(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Cos);
+}
+
+void InstructionSelector::VisitFloat64Cosh(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Cosh);
+}
+
+void InstructionSelector::VisitFloat64Exp(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Exp);
+}
+
+void InstructionSelector::VisitFloat64Expm1(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Expm1);
+}
+
+void InstructionSelector::VisitFloat64Log(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Log);
+}
+
+void InstructionSelector::VisitFloat64Log1p(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Log1p);
+}
+
+void InstructionSelector::VisitFloat64Log2(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Log2);
+}
+
+void InstructionSelector::VisitFloat64Log10(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Log10);
+}
+
+void InstructionSelector::VisitFloat64Pow(Node* node) {
+ VisitFloat64Ieee754Binop(node, kIeee754Float64Pow);
+}
+
+void InstructionSelector::VisitFloat64Sin(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Sin);
+}
+
+void InstructionSelector::VisitFloat64Sinh(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Sinh);
+}
+
+void InstructionSelector::VisitFloat64Tan(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Tan);
+}
+
+void InstructionSelector::VisitFloat64Tanh(Node* node) {
+ VisitFloat64Ieee754Unop(node, kIeee754Float64Tanh);
+}
+
void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,
InstructionOperand& index_operand) {
OperandGenerator g(this);
@@ -1252,6 +1493,10 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
+void InstructionSelector::VisitBitcastWordToTagged(Node* node) {
+ EmitIdentity(node);
+}
+
// 32 bit targets do not implement the following instructions.
#if V8_TARGET_ARCH_32_BIT
@@ -1308,7 +1553,6 @@ void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
UNIMPLEMENTED();
}
-
void InstructionSelector::VisitInt64Mul(Node* node) { UNIMPLEMENTED(); }
@@ -1421,19 +1665,7 @@ void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
#endif // V8_TARGET_ARCH_64_BIT
-void InstructionSelector::VisitFinishRegion(Node* node) {
- OperandGenerator g(this);
- Node* value = node->InputAt(0);
- Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
-}
-
-
-void InstructionSelector::VisitGuard(Node* node) {
- OperandGenerator g(this);
- Node* value = node->InputAt(0);
- Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
-}
-
+void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
void InstructionSelector::VisitParameter(Node* node) {
OperandGenerator g(this);
@@ -1443,9 +1675,7 @@ void InstructionSelector::VisitParameter(Node* node) {
? g.DefineAsDualLocation(
node, linkage()->GetParameterLocation(index),
linkage()->GetParameterSecondaryLocation(index))
- : g.DefineAsLocation(
- node, linkage()->GetParameterLocation(index),
- linkage()->GetParameterType(index).representation());
+ : g.DefineAsLocation(node, linkage()->GetParameterLocation(index));
Emit(kArchNop, op);
}
@@ -1455,18 +1685,16 @@ void InstructionSelector::VisitIfException(Node* node) {
OperandGenerator g(this);
Node* call = node->InputAt(1);
DCHECK_EQ(IrOpcode::kCall, call->opcode());
- const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(call);
- Emit(kArchNop,
- g.DefineAsLocation(node, descriptor->GetReturnLocation(0),
- descriptor->GetReturnType(0).representation()));
+ const CallDescriptor* descriptor = CallDescriptorOf(call->op());
+ Emit(kArchNop, g.DefineAsLocation(node, descriptor->GetReturnLocation(0)));
}
void InstructionSelector::VisitOsrValue(Node* node) {
OperandGenerator g(this);
int index = OpParameter<int>(node);
- Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetOsrValueLocation(index),
- MachineRepresentation::kTagged));
+ Emit(kArchNop,
+ g.DefineAsLocation(node, linkage()->GetOsrValueLocation(index)));
}
@@ -1492,6 +1720,7 @@ void InstructionSelector::VisitProjection(Node* node) {
switch (value->opcode()) {
case IrOpcode::kInt32AddWithOverflow:
case IrOpcode::kInt32SubWithOverflow:
+ case IrOpcode::kInt32MulWithOverflow:
case IrOpcode::kInt64AddWithOverflow:
case IrOpcode::kInt64SubWithOverflow:
case IrOpcode::kTryTruncateFloat32ToInt64:
@@ -1527,7 +1756,7 @@ void InstructionSelector::VisitConstant(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
OperandGenerator g(this);
- const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
+ const CallDescriptor* descriptor = CallDescriptorOf(node->op());
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
@@ -1551,10 +1780,6 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
- IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
- if (hint == IfExceptionHint::kLocallyCaught) {
- flags |= CallDescriptor::kHasLocalCatchHandler;
- }
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
@@ -1574,7 +1799,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
- MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
+ MiscField::encode(static_cast<int>(descriptor->ParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
@@ -1595,16 +1820,13 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::VisitTailCall(Node* node) {
OperandGenerator g(this);
- CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node);
+ CallDescriptor const* descriptor = CallDescriptorOf(node->op());
DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls);
- DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite);
- DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall);
-
- // TODO(turbofan): Relax restriction for stack parameters.
- int stack_param_delta = 0;
- if (linkage()->GetIncomingDescriptor()->CanTailCall(node,
- &stack_param_delta)) {
+ CallDescriptor* caller = linkage()->GetIncomingDescriptor();
+ if (caller->CanTailCall(node)) {
+ const CallDescriptor* callee = CallDescriptorOf(node->op());
+ int stack_param_delta = callee->GetStackParameterDelta(caller);
CallBuffer buffer(zone(), descriptor, nullptr);
// Compute InstructionOperands for inputs and outputs.
@@ -1641,6 +1863,9 @@ void InstructionSelector::VisitTailCall(Node* node) {
case CallDescriptor::kCallJSFunction:
opcode = kArchTailCallJSFunction;
break;
+ case CallDescriptor::kCallAddress:
+ opcode = kArchTailCallAddress;
+ break;
default:
UNREACHABLE();
return;
@@ -1648,10 +1873,12 @@ void InstructionSelector::VisitTailCall(Node* node) {
}
opcode |= MiscField::encode(descriptor->flags());
- buffer.instruction_args.push_back(g.TempImmediate(stack_param_delta));
+ Emit(kArchPrepareTailCall, g.NoOutput());
- Emit(kArchPrepareTailCall, g.NoOutput(),
- g.TempImmediate(stack_param_delta));
+ int first_unused_stack_slot =
+ (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0) +
+ stack_param_delta;
+ buffer.instruction_args.push_back(g.TempImmediate(first_unused_stack_slot));
// Emit the tailcall instruction.
Emit(opcode, 0, nullptr, buffer.instruction_args.size(),
@@ -1717,28 +1944,26 @@ void InstructionSelector::VisitReturn(Node* ret) {
auto value_locations = zone()->NewArray<InstructionOperand>(ret_count);
for (int i = 0; i < ret_count; ++i) {
value_locations[i] =
- g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i),
- linkage()->GetReturnType(i).representation());
+ g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i));
}
Emit(kArchRet, 0, nullptr, ret_count, value_locations);
}
}
-Instruction* InstructionSelector::EmitDeoptimize(InstructionCode opcode,
- InstructionOperand output,
- InstructionOperand a,
- InstructionOperand b,
- Node* frame_state) {
+Instruction* InstructionSelector::EmitDeoptimize(
+ InstructionCode opcode, InstructionOperand output, InstructionOperand a,
+ InstructionOperand b, DeoptimizeReason reason, Node* frame_state) {
size_t output_count = output.IsInvalid() ? 0 : 1;
InstructionOperand inputs[] = {a, b};
size_t input_count = arraysize(inputs);
return EmitDeoptimize(opcode, output_count, &output, input_count, inputs,
- frame_state);
+ reason, frame_state);
}
Instruction* InstructionSelector::EmitDeoptimize(
InstructionCode opcode, size_t output_count, InstructionOperand* outputs,
- size_t input_count, InstructionOperand* inputs, Node* frame_state) {
+ size_t input_count, InstructionOperand* inputs, DeoptimizeReason reason,
+ Node* frame_state) {
OperandGenerator g(this);
FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state);
InstructionOperandVector args(instruction_zone());
@@ -1747,9 +1972,8 @@ Instruction* InstructionSelector::EmitDeoptimize(
args.push_back(inputs[i]);
}
opcode |= MiscField::encode(static_cast<int>(input_count));
- InstructionSequence::StateId const state_id =
- sequence()->AddFrameStateDescriptor(descriptor);
- args.push_back(g.TempImmediate(state_id.ToInt()));
+ int const state_id = sequence()->AddDeoptimizationEntry(descriptor, reason);
+ args.push_back(g.TempImmediate(state_id));
StateObjectDeduplicator deduplicator(instruction_zone());
AddInputsToFrameStateDescriptor(descriptor, frame_state, &g, &deduplicator,
&args, FrameStateInputKind::kAny,
@@ -1758,7 +1982,15 @@ Instruction* InstructionSelector::EmitDeoptimize(
nullptr);
}
-void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
+void InstructionSelector::EmitIdentity(Node* node) {
+ OperandGenerator g(this);
+ Node* value = node->InputAt(0);
+ Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+}
+
+void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind,
+ DeoptimizeReason reason,
+ Node* value) {
InstructionCode opcode = kArchDeoptimize;
switch (kind) {
case DeoptimizeKind::kEager:
@@ -1768,7 +2000,7 @@ void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
opcode |= MiscField::encode(Deoptimizer::SOFT);
break;
}
- EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, value);
+ EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, reason, value);
}
@@ -1777,6 +2009,39 @@ void InstructionSelector::VisitThrow(Node* value) {
Emit(kArchThrowTerminator, g.NoOutput());
}
+void InstructionSelector::VisitDebugBreak(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchDebugBreak, g.NoOutput());
+}
+
+void InstructionSelector::VisitComment(Node* node) {
+ OperandGenerator g(this);
+ InstructionOperand operand(g.UseImmediate(node));
+ Emit(kArchComment, 0, nullptr, 1, &operand);
+}
+
+void InstructionSelector::VisitUnsafePointerAdd(Node* node) {
+#if V8_TARGET_ARCH_64_BIT
+ VisitInt64Add(node);
+#else // V8_TARGET_ARCH_64_BIT
+ VisitInt32Add(node);
+#endif // V8_TARGET_ARCH_64_BIT
+}
+
+void InstructionSelector::VisitRetain(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchNop, g.NoOutput(), g.UseAny(node->InputAt(0)));
+}
+
+bool InstructionSelector::CanProduceSignalingNaN(Node* node) {
+ // TODO(jarin) Improve the heuristic here.
+ if (node->opcode() == IrOpcode::kFloat64Add ||
+ node->opcode() == IrOpcode::kFloat64Sub ||
+ node->opcode() == IrOpcode::kFloat64Mul) {
+ return false;
+ }
+ return true;
+}
FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
Node* state) {