Commit 7a22fdff authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Add initial support for SOFT deopts.

This only introduces the basic support for both SOFT and EAGER deopts in
TurboFan, but doesn't make use of SOFT deopts anywhere yet (there are
some other issues blocking that). Basically every Deoptimize operator
now has a DeoptimizeKind, which can be either kSoft or kEager.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32690}
parent adc37e66
......@@ -496,7 +496,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchDeoptimize: {
int deopt_state_id =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
AssembleDeoptimizerCall(deopt_state_id, bailout_type);
break;
}
case kArchRet:
......
......@@ -594,7 +594,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchDeoptimize: {
int deopt_state_id =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
AssembleDeoptimizerCall(deopt_state_id, bailout_type);
break;
}
case kArchRet:
......
......@@ -36,6 +36,27 @@ BranchHint BranchHintOf(const Operator* const op) {
}
size_t hash_value(DeoptimizeKind kind) { return static_cast<size_t>(kind); }
std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) {
switch (kind) {
case DeoptimizeKind::kEager:
return os << "Eager";
case DeoptimizeKind::kSoft:
return os << "Soft";
}
UNREACHABLE();
return os;
}
DeoptimizeKind DeoptimizeKindOf(const Operator* const op) {
DCHECK_EQ(IrOpcode::kDeoptimize, op->opcode());
return OpParameter<DeoptimizeKind>(op);
}
size_t hash_value(IfExceptionHint hint) { return static_cast<size_t>(hint); }
......@@ -122,7 +143,6 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
V(IfDefault, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
V(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1) \
V(Deoptimize, Operator::kNoThrow, 1, 1, 1, 0, 0, 1) \
V(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1) \
V(OsrNormalEntry, Operator::kFoldable, 0, 1, 1, 0, 1, 1) \
V(OsrLoopEntry, Operator::kFoldable, 0, 1, 1, 0, 1, 1) \
......@@ -231,6 +251,18 @@ struct CommonOperatorGlobalCache final {
CACHED_OP_LIST(CACHED)
#undef CACHED
template <DeoptimizeKind kKind>
struct DeoptimizeOperator final : public Operator1<DeoptimizeKind> {
DeoptimizeOperator()
: Operator1<DeoptimizeKind>( // --
IrOpcode::kDeoptimize, Operator::kNoThrow, // opcode
"Deoptimize", // name
1, 1, 1, 0, 0, 1, // counts
kKind) {} // parameter
};
DeoptimizeOperator<DeoptimizeKind::kEager> kDeoptimizeEagerOperator;
DeoptimizeOperator<DeoptimizeKind::kSoft> kDeoptimizeSoftOperator;
template <IfExceptionHint kCaughtLocally>
struct IfExceptionOperator final : public Operator1<IfExceptionHint> {
IfExceptionOperator()
......@@ -448,6 +480,18 @@ const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
}
const Operator* CommonOperatorBuilder::Deoptimize(DeoptimizeKind kind) {
switch (kind) {
case DeoptimizeKind::kEager:
return &cache_.kDeoptimizeEagerOperator;
case DeoptimizeKind::kSoft:
return &cache_.kDeoptimizeSoftOperator;
}
UNREACHABLE();
return nullptr;
}
const Operator* CommonOperatorBuilder::IfException(IfExceptionHint hint) {
switch (hint) {
case IfExceptionHint::kLocallyCaught:
......
......@@ -51,6 +51,16 @@ std::ostream& operator<<(std::ostream&, BranchHint);
BranchHint BranchHintOf(const Operator* const);
// Deoptimize bailout kind.
enum class DeoptimizeKind : uint8_t { kEager, kSoft };
size_t hash_value(DeoptimizeKind kind);
std::ostream& operator<<(std::ostream&, DeoptimizeKind);
DeoptimizeKind DeoptimizeKindOf(const Operator* const);
// Prediction whether throw-site is surrounded by any local catch-scope.
enum class IfExceptionHint { kLocallyUncaught, kLocallyCaught };
......@@ -124,7 +134,7 @@ class CommonOperatorBuilder final : public ZoneObject {
const Operator* IfValue(int32_t value);
const Operator* IfDefault();
const Operator* Throw();
const Operator* Deoptimize();
const Operator* Deoptimize(DeoptimizeKind kind);
const Operator* Return(int value_input_count = 1);
const Operator* Terminate();
......
......@@ -456,7 +456,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchDeoptimize: {
int deopt_state_id =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
AssembleDeoptimizerCall(deopt_state_id, bailout_type);
break;
}
case kArchRet:
......
......@@ -12,6 +12,7 @@
#include "src/compiler/pipeline.h"
#include "src/compiler/schedule.h"
#include "src/compiler/state-values-utils.h"
#include "src/deoptimizer.h"
namespace v8 {
namespace internal {
......@@ -633,12 +634,9 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
return VisitReturn(input);
}
case BasicBlock::kDeoptimize: {
// If the result itself is a return, return its input.
Node* value =
(input != nullptr && input->opcode() == IrOpcode::kDeoptimize)
? input->InputAt(0)
: input;
return VisitDeoptimize(value);
DeoptimizeKind kind = DeoptimizeKindOf(input->op());
Node* value = input->InputAt(0);
return VisitDeoptimize(kind, value);
}
case BasicBlock::kThrow:
DCHECK_EQ(IrOpcode::kThrow, input->opcode());
......@@ -1406,7 +1404,7 @@ void InstructionSelector::VisitReturn(Node* ret) {
}
void InstructionSelector::VisitDeoptimize(Node* value) {
void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
OperandGenerator g(this);
FrameStateDescriptor* desc = GetFrameStateDescriptor(value);
......@@ -1424,7 +1422,16 @@ void InstructionSelector::VisitDeoptimize(Node* value) {
DCHECK_EQ(args.size(), arg_count);
Emit(kArchDeoptimize, 0, nullptr, arg_count, &args.front(), 0, nullptr);
InstructionCode opcode = kArchDeoptimize;
switch (kind) {
case DeoptimizeKind::kEager:
opcode |= MiscField::encode(Deoptimizer::EAGER);
break;
case DeoptimizeKind::kSoft:
opcode |= MiscField::encode(Deoptimizer::SOFT);
break;
}
Emit(opcode, 0, nullptr, arg_count, &args.front(), 0, nullptr);
}
......
......@@ -213,7 +213,7 @@ class InstructionSelector final {
void VisitGoto(BasicBlock* target);
void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
void VisitSwitch(Node* node, const SwitchInfo& sw);
void VisitDeoptimize(Node* value);
void VisitDeoptimize(DeoptimizeKind kind, Node* value);
void VisitReturn(Node* ret);
void VisitThrow(Node* value);
......
......@@ -298,7 +298,8 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(), frame_state, effect, if_false);
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
......@@ -321,8 +322,9 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
effect, if_false);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
......@@ -439,7 +441,8 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(), frame_state, effect, if_false);
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
......@@ -468,8 +471,9 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
effect, if_false);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
......
......@@ -188,8 +188,9 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
effect, if_false);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
......@@ -207,8 +208,9 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
effect, if_true);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_true);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfFalse(), branch);
......@@ -227,8 +229,9 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
effect, if_false);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
......
......@@ -149,7 +149,8 @@ Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
// TODO(bmeurer): Move MergeControlToEnd() to the AdvancedReducer.
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(), frame_state, effect, control);
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, control);
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
node->TrimInputCount(0);
......@@ -466,7 +467,8 @@ Reduction JSIntrinsicLowering::ReduceThrowNotDateError(Node* node) {
// TODO(bmeurer): Move MergeControlToEnd() to the AdvancedReducer.
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(), frame_state, effect, control);
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, effect, control);
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
node->TrimInputCount(0);
......
......@@ -411,8 +411,9 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
? exit_controls.front()
: graph()->NewNode(common()->Merge(exit_control_count),
exit_control_count, &exit_controls.front());
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
exit_effect, exit_control);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, exit_effect, exit_control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
......@@ -838,8 +839,9 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
? exit_controls.front()
: graph()->NewNode(common()->Merge(exit_control_count),
exit_control_count, &exit_controls.front());
Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
exit_effect, exit_control);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
frame_state, exit_effect, exit_control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
......
......@@ -577,7 +577,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchDeoptimize: {
int deopt_state_id =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
AssembleDeoptimizerCall(deopt_state_id, bailout_type);
break;
}
case kArchRet:
......
......@@ -587,7 +587,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchDeoptimize: {
int deopt_state_id =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
AssembleDeoptimizerCall(deopt_state_id, bailout_type);
break;
}
case kArchRet:
......
......@@ -697,7 +697,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchDeoptimize: {
int deopt_state_id =
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
AssembleDeoptimizerCall(deopt_state_id, Deoptimizer::EAGER);
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
AssembleDeoptimizerCall(deopt_state_id, bailout_type);
break;
}
case kArchRet:
......
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