Unify SoftDeoptimize and Deoptimize hydrogen instructions
BUG=chromium:258519 R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/19528003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15827 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
fa037d1602
commit
8cbbdd066c
@ -701,11 +701,6 @@ LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
@ -427,6 +427,7 @@ class LDummyUse: public LTemplateInstruction<1, 1, 0> {
|
||||
class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
|
||||
public:
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
|
||||
DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
|
||||
};
|
||||
|
||||
|
||||
|
@ -810,12 +810,6 @@ void LCodeGen::DeoptimizeIf(Condition cc,
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
|
||||
ASSERT(!info()->IsStub());
|
||||
DeoptimizeIf(al, environment, Deoptimizer::SOFT);
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
|
||||
ZoneList<Handle<Map> > maps(1, zone());
|
||||
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
||||
@ -5646,11 +5640,15 @@ void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
|
||||
if (instr->hydrogen_value()->IsSoftDeoptimize()) {
|
||||
SoftDeoptimize(instr->environment());
|
||||
} else {
|
||||
DeoptimizeIf(al, instr->environment());
|
||||
Deoptimizer::BailoutType type = instr->hydrogen()->type();
|
||||
// TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
|
||||
// needed return address), even though the implementation of LAZY and EAGER is
|
||||
// now identical. When LAZY is eventually completely folded into EAGER, remove
|
||||
// the special case below.
|
||||
if (info()->IsStub() && type == Deoptimizer::EAGER) {
|
||||
type = Deoptimizer::LAZY;
|
||||
}
|
||||
DeoptimizeIf(al, instr->environment(), type);
|
||||
}
|
||||
|
||||
|
||||
|
@ -284,7 +284,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
LEnvironment* environment,
|
||||
Deoptimizer::BailoutType bailout_type);
|
||||
void DeoptimizeIf(Condition cc, LEnvironment* environment);
|
||||
void SoftDeoptimize(LEnvironment* environment);
|
||||
|
||||
void AddToTranslation(Translation* translation,
|
||||
LOperand* op,
|
||||
|
@ -178,7 +178,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
|
||||
AddInstruction(context_);
|
||||
start_environment->BindContext(context_);
|
||||
|
||||
AddSimulate(BailoutId::StubEntry());
|
||||
Add<HSimulate>(BailoutId::StubEntry());
|
||||
|
||||
NoObservableSideEffectsScope no_effects(this);
|
||||
|
||||
@ -397,9 +397,10 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
|
||||
length));
|
||||
}
|
||||
|
||||
HValue* result = environment()->Pop();
|
||||
checker.ElseDeopt();
|
||||
return result;
|
||||
checker.End();
|
||||
|
||||
return environment()->Pop();
|
||||
}
|
||||
|
||||
|
||||
@ -447,8 +448,11 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
|
||||
AddStore(object, access, AddLoad(boilerplate, access));
|
||||
}
|
||||
|
||||
environment()->Push(object);
|
||||
checker.ElseDeopt();
|
||||
return object;
|
||||
checker.End();
|
||||
|
||||
return environment()->Pop();
|
||||
}
|
||||
|
||||
|
||||
@ -929,8 +933,7 @@ HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() {
|
||||
|
||||
if (FLAG_trace_elements_transitions) {
|
||||
// Tracing elements transitions is the job of the runtime.
|
||||
current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
|
||||
set_current_block(NULL);
|
||||
Add<HDeoptimize>(Deoptimizer::EAGER);
|
||||
} else {
|
||||
info()->MarkAsSavesCallerDoubles();
|
||||
|
||||
|
@ -107,7 +107,7 @@ void HPropagateDeoptimizingMarkPhase::NullifyUnreachableInstructions() {
|
||||
instr->DeleteAndReplaceWith(last_dummy);
|
||||
continue;
|
||||
}
|
||||
if (instr->IsSoftDeoptimize()) {
|
||||
if (instr->IsDeoptimize()) {
|
||||
ASSERT(block->IsDeoptimizing());
|
||||
nullify = true;
|
||||
}
|
||||
|
@ -172,15 +172,6 @@ void HEnvironmentLivenessAnalysisPhase::UpdateLivenessAtInstruction(
|
||||
last_simulate_ = NULL;
|
||||
break;
|
||||
}
|
||||
case HValue::kDeoptimize: {
|
||||
// Keep all environment slots alive.
|
||||
HDeoptimize* deopt = HDeoptimize::cast(instr);
|
||||
for (int i = deopt->first_local_index();
|
||||
i < deopt->first_expression_index(); ++i) {
|
||||
live->Add(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HValue::kSimulate:
|
||||
last_simulate_ = HSimulate::cast(instr);
|
||||
went_live_since_last_simulate_.Clear();
|
||||
|
@ -401,7 +401,7 @@ void HGlobalValueNumberingPhase::ComputeBlockSideEffects() {
|
||||
for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
|
||||
HInstruction* instr = it.Current();
|
||||
side_effects.Add(instr->ChangesFlags());
|
||||
if (instr->IsSoftDeoptimize()) {
|
||||
if (instr->IsDeoptimize()) {
|
||||
block_side_effects_[id].RemoveAll();
|
||||
side_effects.RemoveAll();
|
||||
break;
|
||||
|
@ -2136,16 +2136,6 @@ void HSimulate::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
void HDeoptimize::PrintDataTo(StringStream* stream) {
|
||||
if (OperandCount() == 0) return;
|
||||
OperandAt(0)->PrintNameTo(stream);
|
||||
for (int i = 1; i < OperandCount(); ++i) {
|
||||
stream->Add(" ");
|
||||
OperandAt(i)->PrintNameTo(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HEnterInlined::RegisterReturnTarget(HBasicBlock* return_target,
|
||||
Zone* zone) {
|
||||
ASSERT(return_target->IsInlineReturnTarget());
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "allocation.h"
|
||||
#include "code-stubs.h"
|
||||
#include "data-flow.h"
|
||||
#include "deoptimizer.h"
|
||||
#include "small-pointer-list.h"
|
||||
#include "string-stream.h"
|
||||
#include "v8conversions.h"
|
||||
@ -167,7 +168,6 @@ class LChunkBuilder;
|
||||
V(Shl) \
|
||||
V(Shr) \
|
||||
V(Simulate) \
|
||||
V(SoftDeoptimize) \
|
||||
V(StackCheck) \
|
||||
V(StoreContextSlot) \
|
||||
V(StoreGlobalCell) \
|
||||
@ -1499,16 +1499,20 @@ class HNumericConstraint : public HTemplateInstruction<2> {
|
||||
};
|
||||
|
||||
|
||||
// We insert soft-deoptimize when we hit code with unknown typefeedback,
|
||||
// so that we get a chance of re-optimizing with useful typefeedback.
|
||||
// HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
|
||||
class HSoftDeoptimize: public HTemplateInstruction<0> {
|
||||
class HDeoptimize: public HTemplateInstruction<0> {
|
||||
public:
|
||||
explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
return Representation::None();
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
|
||||
Deoptimizer::BailoutType type() { return type_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
|
||||
|
||||
private:
|
||||
Deoptimizer::BailoutType type_;
|
||||
};
|
||||
|
||||
|
||||
@ -1523,59 +1527,6 @@ class HDebugBreak: public HTemplateInstruction<0> {
|
||||
};
|
||||
|
||||
|
||||
class HDeoptimize: public HControlInstruction {
|
||||
public:
|
||||
HDeoptimize(int environment_length,
|
||||
int first_local_index,
|
||||
int first_expression_index,
|
||||
Zone* zone)
|
||||
: values_(environment_length, zone),
|
||||
first_local_index_(first_local_index),
|
||||
first_expression_index_(first_expression_index) { }
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
return Representation::None();
|
||||
}
|
||||
|
||||
virtual int OperandCount() { return values_.length(); }
|
||||
virtual HValue* OperandAt(int index) const { return values_[index]; }
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
virtual int SuccessorCount() { return 0; }
|
||||
virtual HBasicBlock* SuccessorAt(int i) {
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
virtual void SetSuccessorAt(int i, HBasicBlock* block) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void AddEnvironmentValue(HValue* value, Zone* zone) {
|
||||
values_.Add(NULL, zone);
|
||||
SetOperandAt(values_.length() - 1, value);
|
||||
}
|
||||
int first_local_index() { return first_local_index_; }
|
||||
int first_expression_index() { return first_expression_index_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
|
||||
|
||||
enum UseEnvironment {
|
||||
kNoUses,
|
||||
kUseAll
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void InternalSetOperandAt(int index, HValue* value) {
|
||||
values_[index] = value;
|
||||
}
|
||||
|
||||
private:
|
||||
ZoneList<HValue*> values_;
|
||||
int first_local_index_;
|
||||
int first_expression_index_;
|
||||
};
|
||||
|
||||
|
||||
class HGoto: public HTemplateControlInstruction<1, 0> {
|
||||
public:
|
||||
explicit HGoto(HBasicBlock* target) {
|
||||
|
@ -94,7 +94,7 @@ HBasicBlock* HOsrBuilder::BuildPossibleOsrLoopEntry(
|
||||
}
|
||||
}
|
||||
|
||||
builder_->AddSimulate(osr_entry_id);
|
||||
builder_->Add<HSimulate>(osr_entry_id);
|
||||
builder_->Add<HOsrEntry>(osr_entry_id);
|
||||
HContext* context = builder_->Add<HContext>();
|
||||
environment->BindContext(context);
|
||||
|
228
src/hydrogen.cc
228
src/hydrogen.cc
@ -146,26 +146,6 @@ void HBasicBlock::AddInstruction(HInstruction* instr) {
|
||||
}
|
||||
|
||||
|
||||
HDeoptimize* HBasicBlock::CreateDeoptimize(
|
||||
HDeoptimize::UseEnvironment has_uses) {
|
||||
ASSERT(HasEnvironment());
|
||||
if (has_uses == HDeoptimize::kNoUses)
|
||||
return new(zone()) HDeoptimize(0, 0, 0, zone());
|
||||
|
||||
HEnvironment* environment = last_environment();
|
||||
int first_local_index = environment->first_local_index();
|
||||
int first_expression_index = environment->first_expression_index();
|
||||
HDeoptimize* instr = new(zone()) HDeoptimize(
|
||||
environment->length(), first_local_index, first_expression_index, zone());
|
||||
for (int i = 0; i < environment->length(); i++) {
|
||||
HValue* val = environment->values()->at(i);
|
||||
instr->AddEnvironmentValue(val, zone());
|
||||
}
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
|
||||
HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
|
||||
RemovableSimulate removable) {
|
||||
ASSERT(HasEnvironment());
|
||||
@ -700,13 +680,16 @@ HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
|
||||
: builder_(builder),
|
||||
position_(position),
|
||||
finished_(false),
|
||||
deopt_then_(false),
|
||||
deopt_else_(false),
|
||||
did_then_(false),
|
||||
did_else_(false),
|
||||
did_and_(false),
|
||||
did_or_(false),
|
||||
captured_(false),
|
||||
needs_compare_(true),
|
||||
split_edge_merge_block_(NULL) {
|
||||
split_edge_merge_block_(NULL),
|
||||
merge_block_(NULL) {
|
||||
HEnvironment* env = builder->environment();
|
||||
first_true_block_ = builder->CreateBasicBlock(env->Copy());
|
||||
last_true_block_ = NULL;
|
||||
@ -720,6 +703,8 @@ HGraphBuilder::IfBuilder::IfBuilder(
|
||||
: builder_(builder),
|
||||
position_(RelocInfo::kNoPosition),
|
||||
finished_(false),
|
||||
deopt_then_(false),
|
||||
deopt_else_(false),
|
||||
did_then_(false),
|
||||
did_else_(false),
|
||||
did_and_(false),
|
||||
@ -836,14 +821,13 @@ void HGraphBuilder::IfBuilder::Else() {
|
||||
|
||||
|
||||
void HGraphBuilder::IfBuilder::Deopt() {
|
||||
HBasicBlock* block = builder_->current_block();
|
||||
block->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
|
||||
builder_->set_current_block(NULL);
|
||||
ASSERT(did_then_);
|
||||
if (did_else_) {
|
||||
first_false_block_ = NULL;
|
||||
deopt_else_ = true;
|
||||
} else {
|
||||
first_true_block_ = NULL;
|
||||
deopt_then_ = true;
|
||||
}
|
||||
builder_->Add<HDeoptimize>(Deoptimizer::EAGER);
|
||||
}
|
||||
|
||||
|
||||
@ -868,20 +852,30 @@ void HGraphBuilder::IfBuilder::End() {
|
||||
last_true_block_ = builder_->current_block();
|
||||
}
|
||||
if (first_true_block_ == NULL) {
|
||||
// Deopt on true. Nothing to do, just continue the false block.
|
||||
// Return on true. Nothing to do, just continue the false block.
|
||||
} else if (first_false_block_ == NULL) {
|
||||
// Deopt on false. Nothing to do except switching to the true block.
|
||||
builder_->set_current_block(last_true_block_);
|
||||
} else {
|
||||
HEnvironment* merge_env = last_true_block_->last_environment()->Copy();
|
||||
merge_block_ = builder_->CreateBasicBlock(merge_env);
|
||||
merge_block_ = builder_->graph()->CreateBasicBlock();
|
||||
ASSERT(!finished_);
|
||||
if (!did_else_) Else();
|
||||
ASSERT(!last_true_block_->IsFinished());
|
||||
HBasicBlock* last_false_block = builder_->current_block();
|
||||
ASSERT(!last_false_block->IsFinished());
|
||||
last_true_block_->GotoNoSimulate(merge_block_);
|
||||
last_false_block->GotoNoSimulate(merge_block_);
|
||||
if (deopt_then_) {
|
||||
last_false_block->GotoNoSimulate(merge_block_);
|
||||
builder_->PadEnvironmentForContinuation(last_true_block_,
|
||||
merge_block_);
|
||||
last_true_block_->GotoNoSimulate(merge_block_);
|
||||
} else {
|
||||
last_true_block_->GotoNoSimulate(merge_block_);
|
||||
if (deopt_else_) {
|
||||
builder_->PadEnvironmentForContinuation(last_false_block,
|
||||
merge_block_);
|
||||
}
|
||||
last_false_block->GotoNoSimulate(merge_block_);
|
||||
}
|
||||
builder_->set_current_block(merge_block_);
|
||||
}
|
||||
}
|
||||
@ -991,36 +985,6 @@ HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::AddSimulate(BailoutId id,
|
||||
RemovableSimulate removable) {
|
||||
ASSERT(current_block() != NULL);
|
||||
ASSERT(no_side_effects_scope_count_ == 0);
|
||||
current_block()->AddSimulate(id, removable);
|
||||
}
|
||||
|
||||
|
||||
HReturn* HGraphBuilder::AddReturn(HValue* value) {
|
||||
HValue* context = environment()->LookupContext();
|
||||
int num_parameters = graph()->info()->num_parameters();
|
||||
HValue* params = Add<HConstant>(num_parameters);
|
||||
HReturn* return_instruction = new(graph()->zone())
|
||||
HReturn(value, context, params);
|
||||
current_block()->FinishExit(return_instruction);
|
||||
return return_instruction;
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) {
|
||||
isolate()->counters()->soft_deopts_requested()->Increment();
|
||||
if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return;
|
||||
if (current_block()->IsDeoptimizing()) return;
|
||||
Add<HSoftDeoptimize>();
|
||||
isolate()->counters()->soft_deopts_inserted()->Increment();
|
||||
current_block()->MarkAsDeoptimizing();
|
||||
graph()->set_has_soft_deoptimize(true);
|
||||
}
|
||||
|
||||
|
||||
HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
|
||||
HBasicBlock* b = graph()->CreateBasicBlock();
|
||||
b->SetInitialEnvironment(env);
|
||||
@ -1043,8 +1007,41 @@ HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::FinishExitWithHardDeoptimization(
|
||||
HBasicBlock* continuation) {
|
||||
PadEnvironmentForContinuation(current_block(), continuation);
|
||||
Add<HDeoptimize>(Deoptimizer::EAGER);
|
||||
if (no_side_effects_scope_count_ > 0) {
|
||||
current_block()->GotoNoSimulate(continuation);
|
||||
} else {
|
||||
current_block()->Goto(continuation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HGraphBuilder::PadEnvironmentForContinuation(
|
||||
HBasicBlock* from,
|
||||
HBasicBlock* continuation) {
|
||||
if (continuation->last_environment() != NULL) {
|
||||
// When merging from a deopt block to a continuation, resolve differences in
|
||||
// environment by pushing undefined and popping extra values so that the
|
||||
// environments match during the join.
|
||||
int continuation_env_length = continuation->last_environment()->length();
|
||||
while (continuation_env_length != from->last_environment()->length()) {
|
||||
if (continuation_env_length > from->last_environment()->length()) {
|
||||
from->last_environment()->Push(graph()->GetConstantUndefined());
|
||||
} else {
|
||||
from->last_environment()->Pop();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ASSERT(continuation->predecessors()->length() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HValue* HGraphBuilder::BuildCheckMap(HValue* obj,
|
||||
Handle<Map> map) {
|
||||
Handle<Map> map) {
|
||||
HCheckMaps* check = HCheckMaps::New(obj, map, zone(), top_info());
|
||||
AddInstruction(check);
|
||||
return check;
|
||||
@ -1720,7 +1717,7 @@ HInstruction* HGraphBuilder::BuildUnaryMathOp(
|
||||
input, graph()->GetConstantMinus1());
|
||||
Representation rep = Representation::FromType(type);
|
||||
if (type->Is(Type::None())) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
if (instr->IsBinaryOperation()) {
|
||||
HBinaryOperation* binop = HBinaryOperation::cast(instr);
|
||||
@ -1731,7 +1728,7 @@ HInstruction* HGraphBuilder::BuildUnaryMathOp(
|
||||
}
|
||||
case Token::BIT_NOT:
|
||||
if (type->Is(Type::None())) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
return new(zone()) HBitNot(input);
|
||||
}
|
||||
@ -2639,7 +2636,7 @@ void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
|
||||
ASSERT(!instr->IsControlInstruction());
|
||||
owner()->AddInstruction(instr);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE);
|
||||
owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2681,7 +2678,7 @@ void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
|
||||
owner()->AddInstruction(instr);
|
||||
owner()->Push(instr);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE);
|
||||
owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2737,7 +2734,7 @@ void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
|
||||
// this one isn't actually needed (and wouldn't work if it were targeted).
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
builder->Push(instr);
|
||||
builder->AddSimulate(ast_id, REMOVABLE_SIMULATE);
|
||||
builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
||||
builder->Pop();
|
||||
}
|
||||
BuildBranch(instr);
|
||||
@ -2925,7 +2922,7 @@ bool HOptimizedGraphBuilder::BuildGraph() {
|
||||
VisitVariableDeclaration(scope->function());
|
||||
}
|
||||
VisitDeclarations(scope->declarations());
|
||||
AddSimulate(BailoutId::Declarations());
|
||||
Add<HSimulate>(BailoutId::Declarations());
|
||||
|
||||
HValue* context = environment()->LookupContext();
|
||||
Add<HStackCheck>(context, HStackCheck::kFunctionEntry);
|
||||
@ -2934,7 +2931,7 @@ bool HOptimizedGraphBuilder::BuildGraph() {
|
||||
if (HasStackOverflow()) return false;
|
||||
|
||||
if (current_block() != NULL) {
|
||||
AddReturn(graph()->GetConstantUndefined());
|
||||
Add<HReturn>(graph()->GetConstantUndefined());
|
||||
set_current_block(NULL);
|
||||
}
|
||||
|
||||
@ -3224,10 +3221,10 @@ void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
|
||||
ASSERT(current_block() != NULL);
|
||||
ASSERT(current_block()->HasPredecessor());
|
||||
if (stmt->condition()->ToBooleanIsTrue()) {
|
||||
AddSimulate(stmt->ThenId());
|
||||
Add<HSimulate>(stmt->ThenId());
|
||||
Visit(stmt->then_statement());
|
||||
} else if (stmt->condition()->ToBooleanIsFalse()) {
|
||||
AddSimulate(stmt->ElseId());
|
||||
Add<HSimulate>(stmt->ElseId());
|
||||
Visit(stmt->else_statement());
|
||||
} else {
|
||||
HBasicBlock* cond_true = graph()->CreateBasicBlock();
|
||||
@ -3334,7 +3331,7 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
// Not an inlined return, so an actual one.
|
||||
CHECK_ALIVE(VisitForValue(stmt->expression()));
|
||||
HValue* result = environment()->Pop();
|
||||
AddReturn(result);
|
||||
Add<HReturn>(result);
|
||||
} else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
|
||||
// Return from an inlined construct call. In a test context the return value
|
||||
// will always evaluate to true, in a value context the return value needs
|
||||
@ -3426,7 +3423,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
HValue* context = environment()->LookupContext();
|
||||
|
||||
CHECK_ALIVE(VisitForValue(stmt->tag()));
|
||||
AddSimulate(stmt->EntryId());
|
||||
Add<HSimulate>(stmt->EntryId());
|
||||
HValue* tag_value = Pop();
|
||||
HBasicBlock* first_test_block = current_block();
|
||||
|
||||
@ -3466,7 +3463,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
|
||||
if (!clause->compare_type()->Is(Type::Smi())) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
|
||||
HCompareNumericAndBranch* compare_ =
|
||||
@ -3516,7 +3513,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
normal_block = last_block;
|
||||
last_block = NULL; // Cleared to indicate we've handled it.
|
||||
}
|
||||
} else if (!curr_test_block->end()->IsDeoptimize()) {
|
||||
} else {
|
||||
normal_block = curr_test_block->end()->FirstSuccessor();
|
||||
curr_test_block = curr_test_block->end()->SecondSuccessor();
|
||||
}
|
||||
@ -3570,7 +3567,7 @@ void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
|
||||
HBasicBlock* loop_entry,
|
||||
BreakAndContinueInfo* break_info) {
|
||||
BreakAndContinueScope push(break_info, this);
|
||||
AddSimulate(stmt->StackCheckId());
|
||||
Add<HSimulate>(stmt->StackCheckId());
|
||||
HValue* context = environment()->LookupContext();
|
||||
HStackCheck* stack_check = Add<HStackCheck>(
|
||||
context, HStackCheck::kBackwardsBranch);
|
||||
@ -3731,7 +3728,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
HInstruction* map = Add<HForInPrepareMap>(
|
||||
environment()->LookupContext(), enumerable);
|
||||
AddSimulate(stmt->PrepareId());
|
||||
Add<HSimulate>(stmt->PrepareId());
|
||||
|
||||
HInstruction* array = Add<HForInCacheArray>(
|
||||
enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
|
||||
@ -4328,7 +4325,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
AddInstruction(store);
|
||||
if (store->HasObservableSideEffects()) {
|
||||
AddSimulate(key->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
} else {
|
||||
CHECK_ALIVE(VisitForEffect(value));
|
||||
@ -4493,7 +4490,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
AddSimulate(expr->GetIdForElement(i));
|
||||
Add<HSimulate>(expr->GetIdForElement(i));
|
||||
}
|
||||
|
||||
Drop(1); // array literal index
|
||||
@ -4824,7 +4821,7 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
|
||||
if (!ast_context()->IsEffect()) Push(result_value);
|
||||
store->set_position(position);
|
||||
AddInstruction(store);
|
||||
AddSimulate(assignment_id);
|
||||
Add<HSimulate>(assignment_id);
|
||||
if (!ast_context()->IsEffect()) Drop(1);
|
||||
ast_context()->ReturnValue(result_value);
|
||||
return true;
|
||||
@ -4883,7 +4880,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
||||
// know about and do not want to handle ones we've never seen. Otherwise
|
||||
// use a generic IC.
|
||||
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
|
||||
current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
|
||||
FinishExitWithHardDeoptimization(join);
|
||||
} else {
|
||||
HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
|
||||
instr->set_position(position);
|
||||
@ -4900,10 +4897,10 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
||||
// unoptimized code).
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
if (ast_context()->IsEffect()) {
|
||||
AddSimulate(assignment_id, REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
|
||||
} else {
|
||||
Push(result_value);
|
||||
AddSimulate(assignment_id, REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
|
||||
Drop(1);
|
||||
}
|
||||
}
|
||||
@ -4931,7 +4928,7 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
||||
HValue* value = environment()->ExpressionStackAt(0);
|
||||
HValue* object = environment()->ExpressionStackAt(1);
|
||||
|
||||
if (expr->IsUninitialized()) AddSoftDeoptimize();
|
||||
if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
return BuildStoreNamed(expr, expr->id(), expr->position(),
|
||||
expr->AssignmentId(), prop, object, value, value);
|
||||
} else {
|
||||
@ -4948,7 +4945,7 @@ void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
||||
&has_side_effects);
|
||||
Drop(3);
|
||||
Push(value);
|
||||
AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
return ast_context()->ReturnValue(Pop());
|
||||
}
|
||||
}
|
||||
@ -4977,14 +4974,14 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
||||
}
|
||||
builder.Then();
|
||||
builder.Else();
|
||||
AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT);
|
||||
Add<HDeoptimize>(Deoptimizer::EAGER);
|
||||
builder.End();
|
||||
}
|
||||
HInstruction* instr =
|
||||
Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
|
||||
instr->set_position(position);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(ast_id, REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
||||
}
|
||||
} else {
|
||||
HValue* context = environment()->LookupContext();
|
||||
@ -4994,7 +4991,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
||||
value, function_strict_mode_flag());
|
||||
instr->set_position(position);
|
||||
ASSERT(instr->HasObservableSideEffects());
|
||||
AddSimulate(ast_id, REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5056,7 +5053,7 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
|
||||
instr->set_position(position);
|
||||
AddInstruction(instr);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(id, REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(id, REMOVABLE_SIMULATE);
|
||||
}
|
||||
if (!ast_context()->IsEffect()) Drop(1);
|
||||
return ast_context()->ReturnValue(result_value);
|
||||
@ -5134,7 +5131,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
||||
HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
|
||||
mode, Top());
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -5175,7 +5172,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
||||
if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
|
||||
PushAndAdd(load);
|
||||
if (load->HasObservableSideEffects()) {
|
||||
AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
|
||||
CHECK_ALIVE(VisitForValue(expr->value()));
|
||||
@ -5185,7 +5182,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
||||
HInstruction* instr = BuildBinaryOperation(operation, left, right);
|
||||
PushAndAdd(instr);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(operation->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
|
||||
return BuildStoreNamed(prop, expr->id(), expr->position(),
|
||||
@ -5203,7 +5200,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
||||
false, // is_store
|
||||
&has_side_effects);
|
||||
Push(load);
|
||||
if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
|
||||
CHECK_ALIVE(VisitForValue(expr->value()));
|
||||
HValue* right = Pop();
|
||||
@ -5212,7 +5209,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
||||
HInstruction* instr = BuildBinaryOperation(operation, left, right);
|
||||
PushAndAdd(instr);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(operation->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
|
||||
HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
|
||||
@ -5224,7 +5221,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
||||
Drop(3);
|
||||
Push(instr);
|
||||
ASSERT(has_side_effects); // Stores always have side effects.
|
||||
AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
return ast_context()->ReturnValue(Pop());
|
||||
}
|
||||
|
||||
@ -5346,7 +5343,7 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
|
||||
mode, Top());
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
return ast_context()->ReturnValue(Pop());
|
||||
}
|
||||
@ -5380,7 +5377,7 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
|
||||
HValue* value = environment()->Pop();
|
||||
HThrow* instr = Add<HThrow>(context, value);
|
||||
instr->set_position(expr->position());
|
||||
AddSimulate(expr->id());
|
||||
Add<HSimulate>(expr->id());
|
||||
current_block()->FinishExit(new(zone()) HAbnormalExit);
|
||||
set_current_block(NULL);
|
||||
}
|
||||
@ -5412,7 +5409,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
|
||||
Handle<String> name,
|
||||
Property* expr) {
|
||||
if (expr->IsUninitialized()) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
HValue* context = environment()->LookupContext();
|
||||
return new(zone()) HLoadNamedGeneric(context, object, name);
|
||||
@ -5735,7 +5732,8 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
||||
}
|
||||
|
||||
// Deopt if none of the cases matched.
|
||||
current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
|
||||
NoObservableSideEffectsScope scope(this);
|
||||
FinishExitWithHardDeoptimization(join);
|
||||
set_current_block(join);
|
||||
return is_store ? NULL : Pop();
|
||||
}
|
||||
@ -5771,12 +5769,12 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
|
||||
} else {
|
||||
if (is_store) {
|
||||
if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
instr = BuildStoreKeyedGeneric(obj, key, val);
|
||||
} else {
|
||||
if (expr->AsProperty()->IsUninitialized()) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
instr = BuildLoadKeyedGeneric(obj, key);
|
||||
}
|
||||
@ -5955,10 +5953,10 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
|
||||
&has_side_effects);
|
||||
if (has_side_effects) {
|
||||
if (ast_context()->IsEffect()) {
|
||||
AddSimulate(expr->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
|
||||
} else {
|
||||
Push(load);
|
||||
AddSimulate(expr->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
|
||||
Drop(1);
|
||||
}
|
||||
}
|
||||
@ -6060,7 +6058,7 @@ bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
|
||||
PreProcessCall(call);
|
||||
AddInstruction(call);
|
||||
if (!ast_context()->IsEffect()) Push(call);
|
||||
AddSimulate(expr->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
|
||||
if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
|
||||
}
|
||||
|
||||
@ -6192,7 +6190,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
|
||||
// know about and do not want to handle ones we've never seen. Otherwise
|
||||
// use a generic IC.
|
||||
if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
|
||||
current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
|
||||
FinishExitWithHardDeoptimization(join);
|
||||
} else {
|
||||
HValue* context = environment()->LookupContext();
|
||||
HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
|
||||
@ -6450,7 +6448,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
|
||||
inner_env->BindContext(context);
|
||||
#endif
|
||||
|
||||
AddSimulate(return_id);
|
||||
Add<HSimulate>(return_id);
|
||||
current_block()->UpdateEnvironment(inner_env);
|
||||
HArgumentsObject* arguments_object = NULL;
|
||||
|
||||
@ -7628,7 +7626,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
|
||||
mode, after);
|
||||
if (instr->HasObservableSideEffects()) {
|
||||
AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -7671,7 +7669,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
|
||||
PushAndAdd(load);
|
||||
if (load->HasObservableSideEffects()) {
|
||||
AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
|
||||
after = BuildIncrement(returns_original_input, expr);
|
||||
@ -7694,7 +7692,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
false, // is_store
|
||||
&has_side_effects);
|
||||
Push(load);
|
||||
if (has_side_effects) AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
|
||||
|
||||
after = BuildIncrement(returns_original_input, expr);
|
||||
input = environment()->ExpressionStackAt(0);
|
||||
@ -7711,7 +7709,7 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
environment()->SetExpressionStackAt(0, after);
|
||||
if (returns_original_input) environment()->SetExpressionStackAt(1, input);
|
||||
ASSERT(has_side_effects); // Stores always have side effects.
|
||||
AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7859,12 +7857,12 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
|
||||
}
|
||||
|
||||
if (left_type->Is(Type::None())) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
// TODO(rossberg): we should be able to get rid of non-continuous defaults.
|
||||
left_type = handle(Type::Any(), isolate());
|
||||
}
|
||||
if (right_type->Is(Type::None())) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
right_type = handle(Type::Any(), isolate());
|
||||
}
|
||||
HInstruction* instr = NULL;
|
||||
@ -8214,7 +8212,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
||||
// Cases handled below depend on collected type feedback. They should
|
||||
// soft deoptimize when there is no type feedback.
|
||||
if (combined_type->Is(Type::None())) {
|
||||
AddSoftDeoptimize();
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
combined_type = left_type = right_type = handle(Type::Any(), isolate());
|
||||
}
|
||||
|
||||
@ -8717,7 +8715,7 @@ void HOptimizedGraphBuilder::VisitVariableDeclaration(
|
||||
HStoreContextSlot* store = Add<HStoreContextSlot>(
|
||||
context, variable->index(), HStoreContextSlot::kNoCheck, value);
|
||||
if (store->HasObservableSideEffects()) {
|
||||
AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -8755,7 +8753,7 @@ void HOptimizedGraphBuilder::VisitFunctionDeclaration(
|
||||
HStoreContextSlot* store = Add<HStoreContextSlot>(
|
||||
context, variable->index(), HStoreContextSlot::kNoCheck, value);
|
||||
if (store->HasObservableSideEffects()) {
|
||||
AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
|
||||
Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -137,17 +137,15 @@ class HBasicBlock: public ZoneObject {
|
||||
}
|
||||
|
||||
int PredecessorIndexOf(HBasicBlock* predecessor) const;
|
||||
void AddSimulate(BailoutId ast_id,
|
||||
RemovableSimulate removable = FIXED_SIMULATE) {
|
||||
AddInstruction(CreateSimulate(ast_id, removable));
|
||||
HSimulate* AddSimulate(BailoutId ast_id,
|
||||
RemovableSimulate removable = FIXED_SIMULATE) {
|
||||
HSimulate* instr = CreateSimulate(ast_id, removable);
|
||||
AddInstruction(instr);
|
||||
return instr;
|
||||
}
|
||||
void AssignCommonDominator(HBasicBlock* other);
|
||||
void AssignLoopSuccessorDominators();
|
||||
|
||||
void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses) {
|
||||
FinishExit(CreateDeoptimize(has_uses));
|
||||
}
|
||||
|
||||
// Add the inlined function exit sequence, adding an HLeaveInlined
|
||||
// instruction and updating the bailout environment.
|
||||
void AddLeaveInlined(HValue* return_value, FunctionState* state);
|
||||
@ -182,11 +180,12 @@ class HBasicBlock: public ZoneObject {
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class HGraphBuilder;
|
||||
|
||||
void RegisterPredecessor(HBasicBlock* pred);
|
||||
void AddDominatedBlock(HBasicBlock* block);
|
||||
|
||||
HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
|
||||
HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);
|
||||
|
||||
int block_id_;
|
||||
HGraph* graph_;
|
||||
@ -1023,11 +1022,6 @@ class HGraphBuilder {
|
||||
new(zone()) I(p1, p2, p3, p4, p5, p6, p7, p8)));
|
||||
}
|
||||
|
||||
void AddSimulate(BailoutId id,
|
||||
RemovableSimulate removable = FIXED_SIMULATE);
|
||||
|
||||
HReturn* AddReturn(HValue* value);
|
||||
|
||||
void IncrementInNoSideEffectsScope() {
|
||||
no_side_effects_scope_count_++;
|
||||
}
|
||||
@ -1122,12 +1116,7 @@ class HGraphBuilder {
|
||||
|
||||
void PushAndAdd(HInstruction* instr);
|
||||
|
||||
enum SoftDeoptimizeMode {
|
||||
MUST_EMIT_SOFT_DEOPT,
|
||||
CAN_OMIT_SOFT_DEOPT
|
||||
};
|
||||
|
||||
void AddSoftDeoptimize(SoftDeoptimizeMode mode = CAN_OMIT_SOFT_DEOPT);
|
||||
void FinishExitWithHardDeoptimization(HBasicBlock* continuation);
|
||||
|
||||
class IfBuilder {
|
||||
public:
|
||||
@ -1232,7 +1221,6 @@ class HGraphBuilder {
|
||||
void ElseDeopt() {
|
||||
Else();
|
||||
Deopt();
|
||||
End();
|
||||
}
|
||||
|
||||
void Return(HValue* value);
|
||||
@ -1245,6 +1233,8 @@ class HGraphBuilder {
|
||||
HGraphBuilder* builder_;
|
||||
int position_;
|
||||
bool finished_ : 1;
|
||||
bool deopt_then_ : 1;
|
||||
bool deopt_else_ : 1;
|
||||
bool did_then_ : 1;
|
||||
bool did_else_ : 1;
|
||||
bool did_and_ : 1;
|
||||
@ -1426,12 +1416,68 @@ class HGraphBuilder {
|
||||
|
||||
private:
|
||||
HGraphBuilder();
|
||||
|
||||
void PadEnvironmentForContinuation(HBasicBlock* from,
|
||||
HBasicBlock* continuation);
|
||||
|
||||
CompilationInfo* info_;
|
||||
HGraph* graph_;
|
||||
HBasicBlock* current_block_;
|
||||
int no_side_effects_scope_count_;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
inline HDeoptimize* HGraphBuilder::Add(Deoptimizer::BailoutType type) {
|
||||
if (type == Deoptimizer::SOFT) {
|
||||
isolate()->counters()->soft_deopts_requested()->Increment();
|
||||
if (FLAG_always_opt) return NULL;
|
||||
}
|
||||
if (current_block()->IsDeoptimizing()) return NULL;
|
||||
HDeoptimize* instr = new(zone()) HDeoptimize(type);
|
||||
AddInstruction(instr);
|
||||
if (type == Deoptimizer::SOFT) {
|
||||
isolate()->counters()->soft_deopts_inserted()->Increment();
|
||||
graph()->set_has_soft_deoptimize(true);
|
||||
}
|
||||
current_block()->MarkAsDeoptimizing();
|
||||
return instr;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline HSimulate* HGraphBuilder::Add(BailoutId id,
|
||||
RemovableSimulate removable) {
|
||||
HSimulate* instr = current_block()->CreateSimulate(id, removable);
|
||||
AddInstruction(instr);
|
||||
return instr;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline HSimulate* HGraphBuilder::Add(BailoutId id) {
|
||||
return Add<HSimulate>(id, FIXED_SIMULATE);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline HReturn* HGraphBuilder::Add(HValue* value) {
|
||||
HValue* context = environment()->LookupContext();
|
||||
int num_parameters = graph()->info()->num_parameters();
|
||||
HValue* params = Add<HConstant>(num_parameters);
|
||||
HReturn* return_instruction = new(graph()->zone())
|
||||
HReturn(value, context, params);
|
||||
current_block()->FinishExit(return_instruction);
|
||||
return return_instruction;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline HReturn* HGraphBuilder::Add(HConstant* p1) {
|
||||
return Add<HReturn>(static_cast<HValue*>(p1));
|
||||
}
|
||||
|
||||
|
||||
class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
|
||||
public:
|
||||
// A class encapsulating (lazily-allocated) break and continue blocks for
|
||||
|
@ -1003,12 +1003,6 @@ void LCodeGen::DeoptimizeIf(Condition cc,
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
|
||||
ASSERT(!info()->IsStub());
|
||||
DeoptimizeIf(no_condition, environment, Deoptimizer::SOFT);
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
|
||||
ZoneList<Handle<Map> > maps(1, zone());
|
||||
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
||||
@ -6323,11 +6317,15 @@ void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
|
||||
if (instr->hydrogen_value()->IsSoftDeoptimize()) {
|
||||
SoftDeoptimize(instr->environment());
|
||||
} else {
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
Deoptimizer::BailoutType type = instr->hydrogen()->type();
|
||||
// TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
|
||||
// needed return address), even though the implementation of LAZY and EAGER is
|
||||
// now identical. When LAZY is eventually completely folded into EAGER, remove
|
||||
// the special case below.
|
||||
if (info()->IsStub() && type == Deoptimizer::EAGER) {
|
||||
type = Deoptimizer::LAZY;
|
||||
}
|
||||
DeoptimizeIf(no_condition, instr->environment(), type);
|
||||
}
|
||||
|
||||
|
||||
|
@ -283,7 +283,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
LEnvironment* environment,
|
||||
Deoptimizer::BailoutType bailout_type);
|
||||
void DeoptimizeIf(Condition cc, LEnvironment* environment);
|
||||
void SoftDeoptimize(LEnvironment* environment);
|
||||
|
||||
void AddToTranslation(Translation* translation,
|
||||
LOperand* op,
|
||||
|
@ -754,11 +754,6 @@ LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
@ -424,6 +424,7 @@ class LDummyUse: public LTemplateInstruction<1, 1, 0> {
|
||||
class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
|
||||
public:
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
|
||||
DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
|
||||
};
|
||||
|
||||
|
||||
|
@ -790,14 +790,6 @@ void LCodeGen::DeoptimizeIf(Condition cc,
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::SoftDeoptimize(LEnvironment* environment,
|
||||
Register src1,
|
||||
const Operand& src2) {
|
||||
ASSERT(!info()->IsStub());
|
||||
DeoptimizeIf(al, environment, Deoptimizer::SOFT, src1, src2);
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
|
||||
ZoneList<Handle<Map> > maps(1, zone());
|
||||
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
||||
@ -5649,11 +5641,15 @@ void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
|
||||
if (instr->hydrogen_value()->IsSoftDeoptimize()) {
|
||||
SoftDeoptimize(instr->environment(), zero_reg, Operand(zero_reg));
|
||||
} else {
|
||||
DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg));
|
||||
Deoptimizer::BailoutType type = instr->hydrogen()->type();
|
||||
// TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
|
||||
// needed return address), even though the implementation of LAZY and EAGER is
|
||||
// now identical. When LAZY is eventually completely folded into EAGER, remove
|
||||
// the special case below.
|
||||
if (info()->IsStub() && type == Deoptimizer::EAGER) {
|
||||
type = Deoptimizer::LAZY;
|
||||
}
|
||||
DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg));
|
||||
}
|
||||
|
||||
|
||||
|
@ -284,9 +284,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
LEnvironment* environment,
|
||||
Register src1 = zero_reg,
|
||||
const Operand& src2 = Operand(zero_reg));
|
||||
void SoftDeoptimize(LEnvironment* environment,
|
||||
Register src1 = zero_reg,
|
||||
const Operand& src2 = Operand(zero_reg));
|
||||
|
||||
void AddToTranslation(Translation* translation,
|
||||
LOperand* op,
|
||||
|
@ -706,11 +706,6 @@ LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
@ -424,6 +424,7 @@ class LDummyUse: public LTemplateInstruction<1, 1, 0> {
|
||||
class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
|
||||
public:
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
|
||||
DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
|
||||
};
|
||||
|
||||
|
||||
|
@ -697,12 +697,6 @@ void LCodeGen::DeoptimizeIf(Condition cc,
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
|
||||
ASSERT(!info()->IsStub());
|
||||
DeoptimizeIf(no_condition, environment, Deoptimizer::SOFT);
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
|
||||
ZoneList<Handle<Map> > maps(1, zone());
|
||||
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
||||
@ -5364,11 +5358,15 @@ void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
|
||||
if (instr->hydrogen_value()->IsSoftDeoptimize()) {
|
||||
SoftDeoptimize(instr->environment());
|
||||
} else {
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
Deoptimizer::BailoutType type = instr->hydrogen()->type();
|
||||
// TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
|
||||
// needed return address), even though the implementation of LAZY and EAGER is
|
||||
// now identical. When LAZY is eventually completely folded into EAGER, remove
|
||||
// the special case below.
|
||||
if (info()->IsStub() && type == Deoptimizer::EAGER) {
|
||||
type = Deoptimizer::LAZY;
|
||||
}
|
||||
DeoptimizeIf(no_condition, instr->environment(), type);
|
||||
}
|
||||
|
||||
|
||||
|
@ -245,7 +245,6 @@ class LCodeGen BASE_EMBEDDED {
|
||||
LEnvironment* environment,
|
||||
Deoptimizer::BailoutType bailout_type);
|
||||
void DeoptimizeIf(Condition cc, LEnvironment* environment);
|
||||
void SoftDeoptimize(LEnvironment* environment);
|
||||
void AddToTranslation(Translation* translation,
|
||||
LOperand* op,
|
||||
bool is_tagged,
|
||||
|
@ -710,11 +710,6 @@ LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
|
||||
return AssignEnvironment(new(zone()) LDeoptimize);
|
||||
}
|
||||
|
@ -427,6 +427,7 @@ class LDummyUse: public LTemplateInstruction<1, 1, 0> {
|
||||
class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
|
||||
public:
|
||||
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
|
||||
DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user