Index: src/hydrogen.h |
diff --git a/src/hydrogen.h b/src/hydrogen.h |
index b053fc71c5fc33fbd449da41eadfb18e5cb4db4f..4e97c2e752ff78b26675da9be25c97c844af9471 100644 |
--- a/src/hydrogen.h |
+++ b/src/hydrogen.h |
@@ -67,7 +67,6 @@ class HBasicBlock: public ZoneObject { |
HInstruction* first() const { return first_; } |
HInstruction* last() const { return last_; } |
void set_last(HInstruction* instr) { last_ = instr; } |
- HInstruction* GetLastInstruction(); |
HControlInstruction* end() const { return end_; } |
HLoopInformation* loop_information() const { return loop_information_; } |
const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; } |
@@ -110,9 +109,13 @@ class HBasicBlock: public ZoneObject { |
int LoopNestingDepth() const; |
void SetInitialEnvironment(HEnvironment* env); |
- void ClearEnvironment() { last_environment_ = NULL; } |
+ void ClearEnvironment() { |
+ ASSERT(IsFinished()); |
+ ASSERT(end()->SuccessorCount() == 0); |
+ last_environment_ = NULL; |
+ } |
bool HasEnvironment() const { return last_environment_ != NULL; } |
- void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; } |
+ void UpdateEnvironment(HEnvironment* env); |
HBasicBlock* parent_loop_header() const { return parent_loop_header_; } |
void set_parent_loop_header(HBasicBlock* block) { |
@@ -156,7 +159,11 @@ class HBasicBlock: public ZoneObject { |
// Simulate (caller's environment) |
// Goto (target block) |
bool IsInlineReturnTarget() const { return is_inline_return_target_; } |
- void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; } |
+ void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) { |
+ is_inline_return_target_ = true; |
+ inlined_entry_block_ = inlined_entry_block; |
+ } |
+ HBasicBlock* inlined_entry_block() { return inlined_entry_block_; } |
bool IsDeoptimizing() const { return is_deoptimizing_; } |
void MarkAsDeoptimizing() { is_deoptimizing_ = true; } |
@@ -199,10 +206,12 @@ class HBasicBlock: public ZoneObject { |
int last_instruction_index_; |
ZoneList<int> deleted_phis_; |
HBasicBlock* parent_loop_header_; |
- bool is_inline_return_target_; |
- bool is_deoptimizing_; |
- bool dominates_loop_successors_; |
- bool is_osr_entry_; |
+ // For blocks marked as inline return target: the block with HEnterInlined. |
+ HBasicBlock* inlined_entry_block_; |
+ bool is_inline_return_target_ : 1; |
+ bool is_deoptimizing_ : 1; |
+ bool dominates_loop_successors_ : 1; |
+ bool is_osr_entry_ : 1; |
}; |
@@ -286,6 +295,7 @@ class HGraph: public ZoneObject { |
void RestoreActualValues(); |
void DeadCodeElimination(const char *phase_name); |
void PropagateDeoptimizingMark(); |
+ void AnalyzeAndPruneEnvironmentLiveness(); |
// Returns false if there are phi-uses of the arguments-object |
// which are not supported by the optimizing compiler. |
@@ -363,6 +373,13 @@ class HGraph: public ZoneObject { |
return type_change_checksum_; |
} |
+ void update_maximum_environment_size(int environment_size) { |
+ if (environment_size > maximum_environment_size_) { |
+ maximum_environment_size_ = environment_size; |
+ } |
+ } |
+ int maximum_environment_size() { return maximum_environment_size_; } |
+ |
bool use_optimistic_licm() { |
return use_optimistic_licm_; |
} |
@@ -460,6 +477,7 @@ class HGraph: public ZoneObject { |
bool has_soft_deoptimize_; |
bool depends_on_empty_array_proto_elements_; |
int type_change_checksum_; |
+ int maximum_environment_size_; |
DISALLOW_COPY_AND_ASSIGN(HGraph); |
}; |
@@ -521,6 +539,10 @@ class HEnvironment: public ZoneObject { |
return parameter_count() + specials_count() + local_count(); |
} |
+ int first_local_index() const { |
+ return parameter_count() + specials_count(); |
+ } |
+ |
void Bind(Variable* variable, HValue* value) { |
Bind(IndexFor(variable), value); |
} |
@@ -618,6 +640,22 @@ class HEnvironment: public ZoneObject { |
values_[index] = value; |
} |
+ // Map a variable to an environment index. Parameter indices are shifted |
+ // by 1 (receiver is parameter index -1 but environment index 0). |
+ // Stack-allocated local indices are shifted by the number of parameters. |
+ int IndexFor(Variable* variable) const { |
+ ASSERT(variable->IsStackAllocated()); |
+ int shift = variable->IsParameter() |
+ ? 1 |
+ : parameter_count_ + specials_count_; |
+ return variable->index() + shift; |
+ } |
+ |
+ bool is_local_index(int i) const { |
+ return i >= first_local_index() && |
+ i < first_expression_index(); |
+ } |
+ |
void PrintTo(StringStream* stream); |
void PrintToStd(); |
@@ -645,17 +683,6 @@ class HEnvironment: public ZoneObject { |
void Initialize(int parameter_count, int local_count, int stack_height); |
void Initialize(const HEnvironment* other); |
- // Map a variable to an environment index. Parameter indices are shifted |
- // by 1 (receiver is parameter index -1 but environment index 0). |
- // Stack-allocated local indices are shifted by the number of parameters. |
- int IndexFor(Variable* variable) const { |
- ASSERT(variable->IsStackAllocated()); |
- int shift = variable->IsParameter() |
- ? 1 |
- : parameter_count_ + specials_count_; |
- return variable->index() + shift; |
- } |
- |
Handle<JSFunction> closure_; |
// Value array [parameters] [specials] [locals] [temporaries]. |
ZoneList<HValue*> values_; |
@@ -1535,6 +1562,45 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor { |
HValue* Top() const { return environment()->Top(); } |
void Drop(int n) { environment()->Drop(n); } |
void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); } |
+ bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var, |
+ int index, |
+ HValue* value, |
+ HEnvironment* env) { |
+ if (!FLAG_analyze_environment_liveness) return false; |
+ // |this| and |arguments| are always live; zapping parameters isn't |
+ // safe because function.arguments can inspect them at any time. |
+ return !var->is_this() && |
+ !var->is_arguments() && |
+ !value->IsArgumentsObject() && |
+ env->is_local_index(index); |
+ } |
+ void BindIfLive(Variable* var, HValue* value) { |
+ HEnvironment* env = environment(); |
+ int index = env->IndexFor(var); |
+ env->Bind(index, value); |
+ if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
+ HEnvironmentMarker* bind = |
+ new(zone()) HEnvironmentMarker(HEnvironmentMarker::BIND, index); |
+ AddInstruction(bind); |
+#ifdef DEBUG |
+ bind->set_closure(env->closure()); |
+#endif |
+ } |
+ } |
+ HValue* LookupAndMakeLive(Variable* var) { |
+ HEnvironment* env = environment(); |
+ int index = env->IndexFor(var); |
+ HValue* value = env->Lookup(index); |
+ if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
+ HEnvironmentMarker* lookup = |
+ new(zone()) HEnvironmentMarker(HEnvironmentMarker::LOOKUP, index); |
+ AddInstruction(lookup); |
+#ifdef DEBUG |
+ lookup->set_closure(env->closure()); |
+#endif |
+ } |
+ return value; |
+ } |
// The value of the arguments object is allowed in some but not most value |
// contexts. (It's allowed in all effect contexts and disallowed in all |