void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
- if (!FLAG_analyze_environment_liveness) return;
+ if (!FLAG_analyze_environment_liveness ||
+ !info()->is_deoptimization_enabled()) {
+ return;
+ }
NonLiveFrameStateSlotReplacer replacer(
&state_values_cache_, jsgraph()->UndefinedConstant(),
: builder_(builder),
parameters_count_(scope->num_parameters() + 1),
locals_count_(scope->num_stack_slots()),
- liveness_block_(builder_->liveness_analyzer()->NewBlock()),
+ liveness_block_(IsLivenessAnalysisEnabled()
+ ? builder_->liveness_analyzer()->NewBlock()
+ : nullptr),
values_(builder_->local_zone()),
contexts_(builder_->local_zone()),
control_dependency_(control_dependency),
}
-AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy)
+AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
+ LivenessAnalyzerBlock* liveness_block)
: builder_(copy->builder_),
parameters_count_(copy->parameters_count_),
locals_count_(copy->locals_count_),
+ liveness_block_(liveness_block),
values_(copy->zone()),
contexts_(copy->zone()),
control_dependency_(copy->control_dependency_),
contexts_.reserve(copy->contexts_.size());
contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
copy->contexts_.end());
-
- if (FLAG_analyze_environment_liveness) {
- // Split the liveness blocks.
- copy->liveness_block_ =
- builder_->liveness_analyzer()->NewBlock(copy->liveness_block());
- liveness_block_ =
- builder_->liveness_analyzer()->NewBlock(copy->liveness_block());
- }
}
} else {
DCHECK(variable->IsStackLocal());
values()->at(variable->index() + parameters_count_) = node;
- if (FLAG_analyze_environment_liveness) {
+
+ DCHECK(IsLivenessBlockConsistent());
+ if (liveness_block() != nullptr) {
liveness_block()->Bind(variable->index());
}
}
return values()->at(variable->index() + 1);
} else {
DCHECK(variable->IsStackLocal());
- if (FLAG_analyze_environment_liveness) {
+ DCHECK(IsLivenessBlockConsistent());
+ if (liveness_block() != nullptr) {
liveness_block()->Lookup(variable->index());
}
return values()->at(variable->index() + parameters_count_);
void AstGraphBuilder::Environment::MarkAllLocalsLive() {
- if (FLAG_analyze_environment_liveness) {
+ DCHECK(IsLivenessBlockConsistent());
+ if (liveness_block() != nullptr) {
for (int i = 0; i < locals_count_; i++) {
liveness_block()->Lookup(i);
}
AstGraphBuilder::Environment*
+AstGraphBuilder::Environment::CopyForConditional() {
+ LivenessAnalyzerBlock* copy_liveness_block = nullptr;
+ if (liveness_block() != nullptr) {
+ copy_liveness_block =
+ builder_->liveness_analyzer()->NewBlock(liveness_block());
+ liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
+ }
+ return new (zone()) Environment(this, copy_liveness_block);
+}
+
+
+AstGraphBuilder::Environment*
+AstGraphBuilder::Environment::CopyAsUnreachable() {
+ Environment* env = new (zone()) Environment(this, nullptr);
+ env->MarkAsUnreachable();
+ return env;
+}
+
+
+AstGraphBuilder::Environment*
AstGraphBuilder::Environment::CopyAndShareLiveness() {
- Environment* env = new (zone()) Environment(this);
- if (FLAG_analyze_environment_liveness) {
- env->liveness_block_ = liveness_block();
+ if (liveness_block() != nullptr) {
+ // Finish the current liveness block before copying.
+ liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
}
+ Environment* env = new (zone()) Environment(this, liveness_block());
return env;
}
+AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
+ BitVector* assigned, bool is_osr) {
+ PrepareForLoop(assigned, is_osr);
+ return CopyAndShareLiveness();
+}
+
+
void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
int offset, int count) {
bool should_update = false;
stack_node_, builder()->current_context(),
builder()->GetFunctionClosure(),
builder()->jsgraph()->UndefinedConstant());
- if (FLAG_analyze_environment_liveness) {
+
+ DCHECK(IsLivenessBlockConsistent());
+ if (liveness_block() != nullptr) {
liveness_block()->Checkpoint(result);
}
return result;
}
+bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
+ return FLAG_analyze_environment_liveness &&
+ builder()->info()->is_deoptimization_enabled();
+}
+
+
+bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
+ return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
+ (liveness_block() == nullptr);
+}
+
+
AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
Expression::Context kind)
: kind_(kind), owner_(own), outer_(own->ast_context()) {
}
// Add implicit exception continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
+ // Copy the environment for the success continuation.
+ Environment* success_env = environment()->CopyForConditional();
+
Node* on_exception = graph()->NewNode(common()->IfException(), result);
environment_->UpdateControlDependency(on_exception);
execution_control()->ThrowValue(on_exception);
+ set_environment(success_env);
}
// Add implicit success continuation for throwing nodes.
if (!result->op()->HasProperty(Operator::kNoThrow)) {
if (this->IsMarkedAsUnreachable()) {
Node* other_control = other->control_dependency_;
Node* inputs[] = {other_control};
- liveness_block_ = other->liveness_block_;
control_dependency_ =
graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
effect_dependency_ = other->effect_dependency_;
values_ = other->values_;
contexts_ = other->contexts_;
+ if (IsLivenessAnalysisEnabled()) {
+ liveness_block_ =
+ builder_->liveness_analyzer()->NewBlock(other->liveness_block());
+ }
return;
}
// Record the merge for the local variable liveness calculation.
- // Unfortunately, we have to mirror the logic in the MergeControl method:
- // connect before merge or loop, or create a new merge otherwise.
- if (FLAG_analyze_environment_liveness) {
- if (GetControlDependency()->opcode() != IrOpcode::kLoop &&
- GetControlDependency()->opcode() != IrOpcode::kMerge) {
+ // For loops, we are connecting a back edge into the existing block;
+ // for merges, we create a new merged block.
+ if (IsLivenessAnalysisEnabled()) {
+ if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
liveness_block_ =
builder_->liveness_analyzer()->NewBlock(liveness_block());
}
// Mark this environment as being unreachable.
void MarkAsUnreachable() {
UpdateControlDependency(builder()->jsgraph()->DeadControl());
+ liveness_block_ = nullptr;
}
bool IsMarkedAsUnreachable() {
return GetControlDependency()->opcode() == IrOpcode::kDead;
void Merge(Environment* other);
// Copies this environment at a control-flow split point.
- Environment* CopyForConditional() { return Copy(); }
+ Environment* CopyForConditional();
// Copies this environment to a potentially unreachable control-flow point.
- Environment* CopyAsUnreachable() {
- Environment* env = Copy();
- env->MarkAsUnreachable();
- return env;
- }
+ Environment* CopyAsUnreachable();
// Copies this environment at a loop header control-flow point.
- Environment* CopyForLoop(BitVector* assigned, bool is_osr = false) {
- PrepareForLoop(assigned, is_osr);
- return CopyAndShareLiveness();
- }
+ Environment* CopyForLoop(BitVector* assigned, bool is_osr = false);
private:
AstGraphBuilder* builder_;
Node* locals_node_;
Node* stack_node_;
- explicit Environment(Environment* copy);
- Environment* Copy() { return new (zone()) Environment(this); }
+ explicit Environment(Environment* copy,
+ LivenessAnalyzerBlock* liveness_block);
Environment* CopyAndShareLiveness();
void UpdateStateValues(Node** state_values, int offset, int count);
void UpdateStateValuesWithCache(Node** state_values, int offset, int count);
NodeVector* values() { return &values_; }
NodeVector* contexts() { return &contexts_; }
LivenessAnalyzerBlock* liveness_block() { return liveness_block_; }
+ bool IsLivenessAnalysisEnabled();
+ bool IsLivenessBlockConsistent();
// Prepare environment to be used as loop header.
void PrepareForLoop(BitVector* assigned, bool is_osr = false);