summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/bytecode-graph-builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/bytecode-graph-builder.cc')
-rw-r--r--deps/v8/src/compiler/bytecode-graph-builder.cc70
1 files changed, 45 insertions, 25 deletions
diff --git a/deps/v8/src/compiler/bytecode-graph-builder.cc b/deps/v8/src/compiler/bytecode-graph-builder.cc
index 064d7ee7e4..b59b5a1b84 100644
--- a/deps/v8/src/compiler/bytecode-graph-builder.cc
+++ b/deps/v8/src/compiler/bytecode-graph-builder.cc
@@ -164,6 +164,8 @@ class BytecodeGraphBuilder {
// to the given node and the output value produced by the node is combined.
// Conceptually this frame state is "after" a given operation.
void PrepareFrameState(Node* node, OutputFrameStateCombine combine);
+ void PrepareFrameState(Node* node, OutputFrameStateCombine combine,
+ BailoutId bailout_id);
void BuildCreateArguments(CreateArgumentsType type);
Node* BuildLoadGlobal(NameRef name, uint32_t feedback_slot_index,
@@ -261,6 +263,11 @@ class BytecodeGraphBuilder {
// feedback. Returns kDisallowSpeculation if feedback is insufficient.
SpeculationMode GetSpeculationMode(int slot_id) const;
+ // Helpers for building the implicit FunctionEntry and IterationBody
+ // StackChecks.
+ void BuildFunctionEntryStackCheck();
+ void BuildIterationBodyStackCheck();
+
// Control flow plumbing.
void BuildJump();
void BuildJumpIf(Node* condition);
@@ -355,8 +362,6 @@ class BytecodeGraphBuilder {
currently_peeled_loop_offset_ = offset;
}
bool skip_first_stack_check() const { return skip_first_stack_check_; }
- bool visited_first_stack_check() const { return visited_first_stack_check_; }
- void set_visited_first_stack_check() { visited_first_stack_check_ = true; }
int current_exception_handler() const { return current_exception_handler_; }
void set_current_exception_handler(int index) {
current_exception_handler_ = index;
@@ -395,7 +400,6 @@ class BytecodeGraphBuilder {
int currently_peeled_loop_offset_;
const bool skip_first_stack_check_;
- bool visited_first_stack_check_ = false;
// Merge environments are snapshots of the environment at points where the
// control flow merges. This models a forward data flow propagation of all
@@ -1086,16 +1090,30 @@ void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
void BytecodeGraphBuilder::PrepareFrameState(Node* node,
OutputFrameStateCombine combine) {
if (OperatorProperties::HasFrameStateInput(node->op())) {
+ PrepareFrameState(node, combine,
+ BailoutId(bytecode_iterator().current_offset()));
+ }
+}
+
+void BytecodeGraphBuilder::PrepareFrameState(Node* node,
+ OutputFrameStateCombine combine,
+ BailoutId bailout_id) {
+ if (OperatorProperties::HasFrameStateInput(node->op())) {
// Add the frame state for after the operation. The node in question has
// already been created and had a {Dead} frame state input up until now.
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
DCHECK_EQ(IrOpcode::kDead,
NodeProperties::GetFrameStateInput(node)->opcode());
- BailoutId bailout_id(bytecode_iterator().current_offset());
+ DCHECK_IMPLIES(bailout_id.ToInt() == kFunctionEntryBytecodeOffset,
+ bytecode_iterator().current_offset() == 0);
+ // If we have kFunctionEntryBytecodeOffset as the bailout_id, we want to get
+ // the liveness at the moment of function entry. This is the same as the IN
+ // liveness of the first actual bytecode.
const BytecodeLivenessState* liveness_after =
- bytecode_analysis().GetOutLivenessFor(
- bytecode_iterator().current_offset());
+ bailout_id.ToInt() == kFunctionEntryBytecodeOffset
+ ? bytecode_analysis().GetInLivenessFor(0)
+ : bytecode_analysis().GetOutLivenessFor(bailout_id.ToInt());
Node* frame_state_after =
environment()->Checkpoint(bailout_id, combine, liveness_after);
@@ -1204,6 +1222,21 @@ void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset(
}
}
+void BytecodeGraphBuilder::BuildFunctionEntryStackCheck() {
+ if (!skip_first_stack_check()) {
+ Node* node =
+ NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry));
+ PrepareFrameState(node, OutputFrameStateCombine::Ignore(),
+ BailoutId(kFunctionEntryBytecodeOffset));
+ }
+}
+
+void BytecodeGraphBuilder::BuildIterationBodyStackCheck() {
+ Node* node =
+ NewNode(javascript()->StackCheck(StackCheckKind::kJSIterationBody));
+ environment()->RecordAfterState(node, Environment::kAttachFrameState);
+}
+
// We will iterate through the OSR loop, then its parent, and so on
// until we have reached the outmost loop containing the OSR loop. We do
// not generate nodes for anything before the outermost loop.
@@ -1307,6 +1340,8 @@ void BytecodeGraphBuilder::VisitBytecodes() {
// the last copies of the loops it contains) to be generated by the normal
// bytecode iteration below.
AdvanceToOsrEntryAndPeelLoops();
+ } else {
+ BuildFunctionEntryStackCheck();
}
bool has_one_shot_bytecode = false;
@@ -3229,7 +3264,10 @@ void BytecodeGraphBuilder::VisitJumpIfUndefinedOrNullConstant() {
BuildJumpIfEqual(jsgraph()->NullConstant());
}
-void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
+void BytecodeGraphBuilder::VisitJumpLoop() {
+ BuildIterationBodyStackCheck();
+ BuildJump();
+}
void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) {
interpreter::JumpTableTargetOffsets offsets =
@@ -3252,24 +3290,6 @@ void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() {
BuildSwitchOnSmi(acc_smi);
}
-void BytecodeGraphBuilder::VisitStackCheck() {
- // Note: The stack check kind is determined heuristically: we simply assume
- // that the first seen stack check is at function-entry, and all other stack
- // checks are at iteration-body. An alternative precise solution would be to
- // parameterize the StackCheck bytecode; but this has the caveat of increased
- // code size.
- StackCheckKind kind = StackCheckKind::kJSIterationBody;
- if (!visited_first_stack_check()) {
- set_visited_first_stack_check();
- kind = StackCheckKind::kJSFunctionEntry;
- if (skip_first_stack_check()) return;
- }
-
- PrepareEagerCheckpoint();
- Node* node = NewNode(javascript()->StackCheck(kind));
- environment()->RecordAfterState(node, Environment::kAttachFrameState);
-}
-
void BytecodeGraphBuilder::VisitSetPendingMessage() {
Node* previous_message = NewNode(javascript()->LoadMessage());
NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator());