diff options
Diffstat (limited to 'deps/v8/src/compiler/instruction-selector.cc')
-rw-r--r-- | deps/v8/src/compiler/instruction-selector.cc | 447 |
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) { |