HEnvironment* last_environment = pred->last_environment();
for (int i = 0; i < block->phis()->length(); ++i) {
HPhi* phi = block->phis()->at(i);
- if (phi->merged_index() < last_environment->length()) {
+ // TODO(mstarzinger): The length check below should actually not
+ // be necessary, but some array stubs already rely on it. This
+ // should be investigated and fixed.
+ if (phi->HasMergedIndex() &&
+ phi->merged_index() < last_environment->length()) {
last_environment->SetValueAt(phi->merged_index(), phi);
}
}
HPhi* phi = worklist.RemoveLast();
HBasicBlock* block = phi->block();
phi->DeleteAndReplaceWith(NULL);
- block->RecordDeletedPhi(phi->merged_index());
+ if (phi->HasMergedIndex()) {
+ block->RecordDeletedPhi(phi->merged_index());
+ }
}
}
// Insert a newly created phi into the given block and fill all incoming
-// edges with the given value. The merge index is chosen so that it is
-// unique for this particular scalar replacement index.
+// edges with the given value.
HPhi* HEscapeAnalysisPhase::NewPhiAndInsert(
HBasicBlock* block, HValue* incoming_value, int index) {
Zone* zone = graph()->zone();
- HBasicBlock* pred = block->predecessors()->first();
- int phi_index = pred->last_environment()->length() + cumulative_values_;
- HPhi* phi = new(zone) HPhi(phi_index + index, zone);
+ HPhi* phi = new(zone) HPhi(HPhi::kInvalidMergedIndex, zone);
for (int i = 0; i < block->predecessors()->length(); i++) {
phi->AddInput(incoming_value);
}
non_phi_uses_[i] = 0;
indirect_uses_[i] = 0;
}
- ASSERT(merged_index >= 0);
+ ASSERT(merged_index >= 0 || merged_index == kInvalidMergedIndex);
SetFlag(kFlexibleRepresentation);
SetFlag(kAllowUndefinedAsNaN);
}
bool HasRealUses();
bool IsReceiver() const { return merged_index_ == 0; }
+ bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
int merged_index() const { return merged_index_; }
void SimplifyConstantInputs();
+ // Marker value representing an invalid merge index.
+ static const int kInvalidMergedIndex = -1;
+
protected:
virtual void DeleteFromGraph();
virtual void InternalSetOperandAt(int index, HValue* value) {
const ZoneList<HPhi*>* phis = osr_loop_entry_->phis();
for (int j = 0; j < phis->length(); j++) {
HPhi* phi = phis->at(j);
+ ASSERT(phi->HasMergedIndex());
osr_values_->at(phi->merged_index())->set_incoming_value(phi);
}
}
}
+HPhi* HBasicBlock::AddNewPhi(int merged_index) {
+ if (graph()->IsInsideNoSideEffectsScope()) {
+ merged_index = HPhi::kInvalidMergedIndex;
+ }
+ HPhi* phi = new(zone()) HPhi(merged_index, zone());
+ AddPhi(phi);
+ return phi;
+}
+
+
HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
RemovableSimulate removable) {
ASSERT(HasEnvironment());
UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
}
- if (add_simulate) AddSimulate(BailoutId::None());
+ if (add_simulate) AddNewSimulate(BailoutId::None());
HGoto* instr = new(zone()) HGoto(block);
Finish(instr);
}
AddInstruction(new(zone()) HLeaveInlined());
UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
last_environment()->Push(return_value);
- AddSimulate(BailoutId::None());
+ AddNewSimulate(BailoutId::None());
HGoto* instr = new(zone()) HGoto(target);
Finish(instr);
}
HValue* terminating,
Token::Value token) {
HEnvironment* env = builder_->environment();
- phi_ = new(zone()) HPhi(env->values()->length(), zone());
- header_block_->AddPhi(phi_);
+ phi_ = header_block_->AddNewPhi(env->values()->length());
phi_->AddInput(initial);
env->Push(initial);
builder_->current_block()->GotoNoSimulate(header_block_);
HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
ASSERT(current_block() != NULL);
current_block()->AddInstruction(instr);
- if (no_side_effects_scope_count_ > 0) {
+ if (graph()->IsInsideNoSideEffectsScope()) {
instr->SetFlag(HValue::kHasNoObservableSideEffects);
}
return instr;
void HGraphBuilder::AddSimulate(BailoutId id,
RemovableSimulate removable) {
ASSERT(current_block() != NULL);
- ASSERT(no_side_effects_scope_count_ == 0);
- current_block()->AddSimulate(id, removable);
+ ASSERT(!graph()->IsInsideNoSideEffectsScope());
+ current_block()->AddNewSimulate(id, removable);
}
const char* reason, HBasicBlock* continuation) {
PadEnvironmentForContinuation(current_block(), continuation);
Add<HDeoptimize>(reason, Deoptimizer::EAGER);
- if (no_side_effects_scope_count_ > 0) {
+ if (graph()->IsInsideNoSideEffectsScope()) {
current_block()->GotoNoSimulate(continuation);
} else {
current_block()->Goto(continuation);
has_soft_deoptimize_(false),
depends_on_empty_array_proto_elements_(false),
type_change_checksum_(0),
- maximum_environment_size_(0) {
+ maximum_environment_size_(0),
+ no_side_effects_scope_count_(0) {
if (info->IsStub()) {
HydrogenCodeStub* stub = info->code_stub();
CodeStubInterfaceDescriptor* descriptor =
// There is already a phi for the i'th value.
HPhi* phi = HPhi::cast(value);
// Assert index is correct and that we haven't missed an incoming edge.
- ASSERT(phi->merged_index() == i);
+ ASSERT(phi->merged_index() == i || !phi->HasMergedIndex());
ASSERT(phi->OperandCount() == block->predecessors()->length());
phi->AddInput(other->values_[i]);
} else if (values_[i] != other->values_[i]) {
// There is a fresh value on the incoming edge, a phi is needed.
ASSERT(values_[i] != NULL && other->values_[i] != NULL);
- HPhi* phi = new(zone()) HPhi(i, zone());
+ HPhi* phi = block->AddNewPhi(i);
HValue* old_value = values_[i];
for (int j = 0; j < block->predecessors()->length(); j++) {
phi->AddInput(old_value);
}
phi->AddInput(other->values_[i]);
this->values_[i] = phi;
- block->AddPhi(phi);
}
}
}
HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
HEnvironment* new_env = Copy();
for (int i = 0; i < values_.length(); ++i) {
- HPhi* phi = new(zone()) HPhi(i, zone());
+ HPhi* phi = loop_header->AddNewPhi(i);
phi->AddInput(values_[i]);
new_env->values_[i] = phi;
- loop_header->AddPhi(phi);
}
new_env->ClearHistory();
return new_env;
}
int PredecessorIndexOf(HBasicBlock* predecessor) const;
- HSimulate* AddSimulate(BailoutId ast_id,
- RemovableSimulate removable = FIXED_SIMULATE) {
+ HPhi* AddNewPhi(int merged_index);
+ HSimulate* AddNewSimulate(BailoutId ast_id,
+ RemovableSimulate removable = FIXED_SIMULATE) {
HSimulate* instr = CreateSimulate(ast_id, removable);
AddInstruction(instr);
return instr;
uint32_instructions_->Add(instr, zone());
}
+ void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
+ void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
+ bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; }
+
private:
HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
int32_t integer_value);
bool depends_on_empty_array_proto_elements_;
int type_change_checksum_;
int maximum_environment_size_;
+ int no_side_effects_scope_count_;
DISALLOW_COPY_AND_ASSIGN(HGraph);
};
explicit HGraphBuilder(CompilationInfo* info)
: info_(info),
graph_(NULL),
- current_block_(NULL),
- no_side_effects_scope_count_(0) {}
+ current_block_(NULL) {}
virtual ~HGraphBuilder() {}
HBasicBlock* current_block() const { return current_block_; }
AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)));
}
- void AddSimulate(BailoutId id,
- RemovableSimulate removable = FIXED_SIMULATE);
-
- void IncrementInNoSideEffectsScope() {
- no_side_effects_scope_count_++;
- }
-
- void DecrementInNoSideEffectsScope() {
- no_side_effects_scope_count_--;
- }
+ void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
protected:
virtual bool BuildGraph() = 0;
bool finished_;
};
- class NoObservableSideEffectsScope {
- public:
- explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
- builder_(builder) {
- builder_->IncrementInNoSideEffectsScope();
- }
- ~NoObservableSideEffectsScope() {
- builder_->DecrementInNoSideEffectsScope();
- }
-
- private:
- HGraphBuilder* builder_;
- };
-
HValue* BuildNewElementsCapacity(HValue* old_capacity);
void BuildNewSpaceArrayCheck(HValue* length,
CompilationInfo* info_;
HGraph* graph_;
HBasicBlock* current_block_;
- int no_side_effects_scope_count_;
};
};
+class NoObservableSideEffectsScope {
+ public:
+ explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
+ builder_(builder) {
+ builder_->graph()->IncrementInNoSideEffectsScope();
+ }
+ ~NoObservableSideEffectsScope() {
+ builder_->graph()->DecrementInNoSideEffectsScope();
+ }
+
+ private:
+ HGraphBuilder* builder_;
+};
+
+
} } // namespace v8::internal
#endif // V8_HYDROGEN_H_
HEnvironment* last_environment = pred->last_environment();
for (int i = 0; i < block->phis()->length(); ++i) {
HPhi* phi = block->phis()->at(i);
- if (phi->merged_index() < last_environment->length()) {
+ // TODO(mstarzinger): The length check below should actually not
+ // be necessary, but some array stubs already rely on it. This
+ // should be investigated and fixed.
+ if (phi->HasMergedIndex() &&
+ phi->merged_index() < last_environment->length()) {
last_environment->SetValueAt(phi->merged_index(), phi);
}
}
HEnvironment* last_environment = pred->last_environment();
for (int i = 0; i < block->phis()->length(); ++i) {
HPhi* phi = block->phis()->at(i);
- if (phi->merged_index() < last_environment->length()) {
+ // TODO(mstarzinger): The length check below should actually not
+ // be necessary, but some array stubs already rely on it. This
+ // should be investigated and fixed.
+ if (phi->HasMergedIndex() &&
+ phi->merged_index() < last_environment->length()) {
last_environment->SetValueAt(phi->merged_index(), phi);
}
}
HEnvironment* last_environment = pred->last_environment();
for (int i = 0; i < block->phis()->length(); ++i) {
HPhi* phi = block->phis()->at(i);
- if (phi->merged_index() < last_environment->length()) {
+ // TODO(mstarzinger): The length check below should actually not
+ // be necessary, but some array stubs already rely on it. This
+ // should be investigated and fixed.
+ if (phi->HasMergedIndex() &&
+ phi->merged_index() < last_environment->length()) {
last_environment->SetValueAt(phi->merged_index(), phi);
}
}