Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Unified Diff: src/compiler/bytecode-graph-builder.cc

Issue 2958253002: [turbofan] Replace uninitialized JSConstruct nodes with SOFT deopt. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/bytecode-graph-builder.h ('k') | src/compiler/js-call-reducer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/bytecode-graph-builder.cc
diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc
index e282095711cc1142f23c5517b2078179dabf4ad6..4a10958b160782127a8ceb730236f81e247bb785 100644
--- a/src/compiler/bytecode-graph-builder.cc
+++ b/src/compiler/bytecode-graph-builder.cc
@@ -1583,28 +1583,63 @@ void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
Environment::kAttachFrameState);
}
-Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments(
- const Operator* op, Node* callee, Node* new_target,
- interpreter::Register receiver, size_t reg_count) {
- int arg_count = static_cast<int>(reg_count);
+Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister(
+ Node* target, Node* new_target, interpreter::Register first_arg,
+ int arg_count) {
// arity is args + callee and new target.
int arity = arg_count + 2;
Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
- all[0] = callee;
- int first_arg_index = receiver.index();
+ all[0] = target;
+ int first_arg_index = first_arg.index();
for (int i = 0; i < arg_count; ++i) {
all[1 + i] = environment()->LookupRegister(
interpreter::Register(first_arg_index + i));
}
all[arity - 1] = new_target;
- Node* value = MakeNode(op, arity, all, false);
- return value;
+ return all;
+}
+
+Node* BytecodeGraphBuilder::ProcessConstructArguments(const Operator* op,
+ Node* const* args,
+ int arg_count) {
+ return MakeNode(op, arg_count, args, false);
+}
+
+void BytecodeGraphBuilder::VisitConstruct() {
+ PrepareEagerCheckpoint();
+ interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
+ interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
+ size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
+ // Slot index of 0 is used indicate no feedback slot is available. Assert
+ // the assumption that slot index 0 is never a valid feedback slot.
+ STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
+ int const slot_id = bytecode_iterator().GetIndexOperand(3);
+ VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
+
+ Node* new_target = environment()->LookupAccumulator();
+ Node* callee = environment()->LookupRegister(callee_reg);
+
+ CallFrequency frequency = ComputeCallFrequency(slot_id);
+ const Operator* op = javascript()->Construct(
+ static_cast<uint32_t>(reg_count + 2), frequency, feedback);
+ int arg_count = static_cast<int>(reg_count);
+ Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
+ first_reg, arg_count);
+ Node* node = nullptr;
+ if (Node* simplified = TryBuildSimplifiedConstruct(
+ op, args, static_cast<int>(arg_count), feedback.slot())) {
+ if (environment() == nullptr) return;
+ node = simplified;
+ } else {
+ node = ProcessConstructArguments(op, args, 2 + arg_count);
+ }
+ environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitConstructWithSpread() {
PrepareEagerCheckpoint();
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
- interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
+ interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
Node* new_target = environment()->LookupAccumulator();
@@ -1612,8 +1647,10 @@ void BytecodeGraphBuilder::VisitConstructWithSpread() {
const Operator* op =
javascript()->ConstructWithSpread(static_cast<uint32_t>(reg_count + 2));
- Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target,
- receiver, reg_count);
+ int arg_count = static_cast<int>(reg_count);
+ Node* const* args = GetConstructArgumentsFromRegister(callee, new_target,
+ first_reg, arg_count);
+ Node* value = ProcessConstructArguments(op, args, 2 + arg_count);
environment()->BindAccumulator(value, Environment::kAttachFrameState);
}
@@ -1630,46 +1667,6 @@ void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
environment()->BindAccumulator(value, Environment::kAttachFrameState);
}
-Node* BytecodeGraphBuilder::ProcessConstructArguments(
- const Operator* call_new_op, Node* callee, Node* new_target,
- interpreter::Register receiver, size_t reg_count) {
- int arg_count = static_cast<int>(reg_count);
- // arity is args + callee and new target.
- int arity = arg_count + 2;
- Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
- all[0] = callee;
- int first_arg_index = receiver.index();
- for (int i = 0; i < arg_count; ++i) {
- all[1 + i] = environment()->LookupRegister(
- interpreter::Register(first_arg_index + i));
- }
- all[arity - 1] = new_target;
- Node* value = MakeNode(call_new_op, arity, all, false);
- return value;
-}
-
-void BytecodeGraphBuilder::VisitConstruct() {
- PrepareEagerCheckpoint();
- interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
- interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
- size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
- // Slot index of 0 is used indicate no feedback slot is available. Assert
- // the assumption that slot index 0 is never a valid feedback slot.
- STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
- int const slot_id = bytecode_iterator().GetIndexOperand(3);
- VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
-
- Node* new_target = environment()->LookupAccumulator();
- Node* callee = environment()->LookupRegister(callee_reg);
-
- CallFrequency frequency = ComputeCallFrequency(slot_id);
- const Operator* call = javascript()->Construct(
- static_cast<uint32_t>(reg_count + 2), frequency, feedback);
- Node* value =
- ProcessConstructArguments(call, callee, new_target, receiver, reg_count);
- environment()->BindAccumulator(value, Environment::kAttachFrameState);
-}
-
void BytecodeGraphBuilder::VisitThrow() {
BuildLoopExitsForFunctionExit();
Node* value = environment()->LookupAccumulator();
@@ -2693,6 +2690,25 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedCall(const Operator* op,
return nullptr;
}
+Node* BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op,
+ Node* const* args,
+ int arg_count,
+ FeedbackSlot slot) {
+ // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
+ // pruned from the graph by a soft-deopt. It can happen that a CallIC that
+ // control-dominates the OSR entry is still in "uninitialized" state.
+ if (!osr_ast_id_.IsNone()) return nullptr;
+ Node* effect = environment()->GetEffectDependency();
+ Node* control = environment()->GetControlDependency();
+ Reduction early_reduction = type_hint_lowering().ReduceConstructOperation(
+ op, args, arg_count, effect, control, slot);
+ if (early_reduction.Changed()) {
+ ApplyEarlyReduction(early_reduction);
+ return early_reduction.replacement();
+ }
+ return nullptr;
+}
+
Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
Node* receiver,
FeedbackSlot slot) {
« no previous file with comments | « src/compiler/bytecode-graph-builder.h ('k') | src/compiler/js-call-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698