Reapply "Shuffle around deopt id allocation to give the flow graph builder a chance to record other data as they are allocated".
- Fix inlining of new List(n) to propogate deopt id. - Fix CreateArrayOpt to check for a Smi length. R=vegorov@google.com Review-Url: https://codereview.chromium.org/2900963008 .
This commit is contained in:
@@ -710,7 +710,7 @@ bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
||||
StrictCompareInstr* comp = new (Z)
|
||||
StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
|
||||
new (Z) Value(left), new (Z) Value(right),
|
||||
false); // No number check.
|
||||
/* number_check = */ false, Thread::kNoDeoptId);
|
||||
ReplaceCall(call, comp);
|
||||
return true;
|
||||
}
|
||||
@@ -1441,10 +1441,9 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
||||
ConstantInstr* cid =
|
||||
flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid)));
|
||||
|
||||
StrictCompareInstr* check_cid =
|
||||
new (Z) StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
|
||||
new (Z) Value(left_cid), new (Z) Value(cid),
|
||||
false); // No number check.
|
||||
StrictCompareInstr* check_cid = new (Z) StrictCompareInstr(
|
||||
call->token_pos(), Token::kEQ_STRICT, new (Z) Value(left_cid),
|
||||
new (Z) Value(cid), /* number_check = */ false, Thread::kNoDeoptId);
|
||||
ReplaceCall(call, check_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ JoinEntryInstr* BranchSimplifier::ToJoinEntry(Zone* zone,
|
||||
// Convert a target block into a join block. Branches will be duplicated
|
||||
// so the former true and false targets become joins of the control flows
|
||||
// from all the duplicated branches.
|
||||
JoinEntryInstr* join =
|
||||
new (zone) JoinEntryInstr(target->block_id(), target->try_index());
|
||||
JoinEntryInstr* join = new (zone) JoinEntryInstr(
|
||||
target->block_id(), target->try_index(), Thread::kNoDeoptId);
|
||||
join->InheritDeoptTarget(zone, target);
|
||||
join->LinkTo(target->next());
|
||||
join->set_last_instruction(target->last_instruction());
|
||||
@@ -82,7 +82,8 @@ BranchInstr* BranchSimplifier::CloneBranch(Zone* zone,
|
||||
ComparisonInstr* comparison = branch->comparison();
|
||||
ComparisonInstr* new_comparison =
|
||||
comparison->CopyWithNewOperands(new_left, new_right);
|
||||
BranchInstr* new_branch = new (zone) BranchInstr(new_comparison);
|
||||
BranchInstr* new_branch =
|
||||
new (zone) BranchInstr(new_comparison, Thread::kNoDeoptId);
|
||||
return new_branch;
|
||||
}
|
||||
|
||||
@@ -183,20 +184,24 @@ void BranchSimplifier::Simplify(FlowGraph* flow_graph) {
|
||||
|
||||
// Connect the branch to the true and false joins, via empty target
|
||||
// blocks.
|
||||
TargetEntryInstr* true_target = new (zone) TargetEntryInstr(
|
||||
flow_graph->max_block_id() + 1, block->try_index());
|
||||
TargetEntryInstr* true_target =
|
||||
new (zone) TargetEntryInstr(flow_graph->max_block_id() + 1,
|
||||
block->try_index(), Thread::kNoDeoptId);
|
||||
true_target->InheritDeoptTarget(zone, join_true);
|
||||
TargetEntryInstr* false_target = new (zone) TargetEntryInstr(
|
||||
flow_graph->max_block_id() + 2, block->try_index());
|
||||
TargetEntryInstr* false_target =
|
||||
new (zone) TargetEntryInstr(flow_graph->max_block_id() + 2,
|
||||
block->try_index(), Thread::kNoDeoptId);
|
||||
false_target->InheritDeoptTarget(zone, join_false);
|
||||
flow_graph->set_max_block_id(flow_graph->max_block_id() + 2);
|
||||
*new_branch->true_successor_address() = true_target;
|
||||
*new_branch->false_successor_address() = false_target;
|
||||
GotoInstr* goto_true = new (zone) GotoInstr(join_true);
|
||||
GotoInstr* goto_true =
|
||||
new (zone) GotoInstr(join_true, Thread::kNoDeoptId);
|
||||
goto_true->InheritDeoptTarget(zone, join_true);
|
||||
true_target->LinkTo(goto_true);
|
||||
true_target->set_last_instruction(goto_true);
|
||||
GotoInstr* goto_false = new (zone) GotoInstr(join_false);
|
||||
GotoInstr* goto_false =
|
||||
new (zone) GotoInstr(join_false, Thread::kNoDeoptId);
|
||||
goto_false->InheritDeoptTarget(zone, join_false);
|
||||
false_target->LinkTo(goto_false);
|
||||
false_target->set_last_instruction(goto_false);
|
||||
@@ -295,8 +300,9 @@ void IfConverter::Simplify(FlowGraph* flow_graph) {
|
||||
|
||||
ComparisonInstr* new_comparison = comparison->CopyWithNewOperands(
|
||||
comparison->left()->Copy(zone), comparison->right()->Copy(zone));
|
||||
IfThenElseInstr* if_then_else = new (zone) IfThenElseInstr(
|
||||
new_comparison, if_true->Copy(zone), if_false->Copy(zone));
|
||||
IfThenElseInstr* if_then_else = new (zone)
|
||||
IfThenElseInstr(new_comparison, if_true->Copy(zone),
|
||||
if_false->Copy(zone), Thread::kNoDeoptId);
|
||||
flow_graph->InsertBefore(branch, if_then_else, NULL,
|
||||
FlowGraph::kValue);
|
||||
|
||||
|
||||
@@ -1551,7 +1551,8 @@ void ConstantPropagator::EliminateRedundantBranches() {
|
||||
// Drop the comparison, which does not have side effects
|
||||
JoinEntryInstr* join = if_true->AsJoinEntry();
|
||||
if (join->phis() == NULL) {
|
||||
GotoInstr* jump = new (Z) GotoInstr(if_true->AsJoinEntry());
|
||||
GotoInstr* jump =
|
||||
new (Z) GotoInstr(if_true->AsJoinEntry(), Thread::kNoDeoptId);
|
||||
jump->InheritDeoptTarget(Z, branch);
|
||||
|
||||
Instruction* previous = branch->previous();
|
||||
@@ -1694,16 +1695,16 @@ void ConstantPropagator::Transform() {
|
||||
ASSERT(reachable_->Contains(if_false->preorder_number()));
|
||||
ASSERT(if_false->parallel_move() == NULL);
|
||||
ASSERT(if_false->loop_info() == NULL);
|
||||
join =
|
||||
new (Z) JoinEntryInstr(if_false->block_id(), if_false->try_index());
|
||||
join = new (Z) JoinEntryInstr(
|
||||
if_false->block_id(), if_false->try_index(), Thread::kNoDeoptId);
|
||||
join->InheritDeoptTarget(Z, if_false);
|
||||
if_false->UnuseAllInputs();
|
||||
next = if_false->next();
|
||||
} else if (!reachable_->Contains(if_false->preorder_number())) {
|
||||
ASSERT(if_true->parallel_move() == NULL);
|
||||
ASSERT(if_true->loop_info() == NULL);
|
||||
join =
|
||||
new (Z) JoinEntryInstr(if_true->block_id(), if_true->try_index());
|
||||
join = new (Z) JoinEntryInstr(if_true->block_id(), if_true->try_index(),
|
||||
Thread::kNoDeoptId);
|
||||
join->InheritDeoptTarget(Z, if_true);
|
||||
if_true->UnuseAllInputs();
|
||||
next = if_true->next();
|
||||
@@ -1714,7 +1715,7 @@ void ConstantPropagator::Transform() {
|
||||
// Drop the comparison, which does not have side effects as long
|
||||
// as it is a strict compare (the only one we can determine is
|
||||
// constant with the current analysis).
|
||||
GotoInstr* jump = new (Z) GotoInstr(join);
|
||||
GotoInstr* jump = new (Z) GotoInstr(join, Thread::kNoDeoptId);
|
||||
jump->InheritDeoptTarget(Z, branch);
|
||||
|
||||
Instruction* previous = branch->previous();
|
||||
|
||||
@@ -1018,7 +1018,8 @@ void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
|
||||
for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
|
||||
if (i == CurrentContextEnvIndex()) {
|
||||
if (function().IsClosureFunction()) {
|
||||
CurrentContextInstr* context = new CurrentContextInstr();
|
||||
CurrentContextInstr* context =
|
||||
new CurrentContextInstr(Thread::kNoDeoptId);
|
||||
context->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
|
||||
AddToInitialDefinitions(context);
|
||||
env.Add(context);
|
||||
|
||||
+185
-142
@@ -173,8 +173,8 @@ intptr_t FlowGraphBuilder::context_level() const {
|
||||
JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) {
|
||||
if (label != label_) return NULL;
|
||||
if (break_target_ == NULL) {
|
||||
break_target_ = new (owner()->zone())
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), try_index());
|
||||
break_target_ = new (owner()->zone()) JoinEntryInstr(
|
||||
owner()->AllocateBlockId(), try_index(), owner()->GetNextDeoptId());
|
||||
}
|
||||
return break_target_;
|
||||
}
|
||||
@@ -246,8 +246,8 @@ class NestedLoop : public NestedStatement {
|
||||
JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) {
|
||||
if (label != this->label()) return NULL;
|
||||
if (continue_target_ == NULL) {
|
||||
continue_target_ = new (owner()->zone())
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), try_index());
|
||||
continue_target_ = new (owner()->zone()) JoinEntryInstr(
|
||||
owner()->AllocateBlockId(), try_index(), owner()->GetNextDeoptId());
|
||||
}
|
||||
return continue_target_;
|
||||
}
|
||||
@@ -289,8 +289,8 @@ JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) {
|
||||
for (intptr_t i = 0; i < case_labels_.length(); ++i) {
|
||||
if (label != case_labels_[i]) continue;
|
||||
if (case_targets_[i] == NULL) {
|
||||
case_targets_[i] = new (owner()->zone())
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), try_index());
|
||||
case_targets_[i] = new (owner()->zone()) JoinEntryInstr(
|
||||
owner()->AllocateBlockId(), try_index(), owner()->GetNextDeoptId());
|
||||
}
|
||||
return case_targets_[i];
|
||||
}
|
||||
@@ -442,7 +442,8 @@ Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
|
||||
// Create a join of the returns.
|
||||
intptr_t join_id = caller_graph_->max_block_id() + 1;
|
||||
caller_graph_->set_max_block_id(join_id);
|
||||
JoinEntryInstr* join = new (Z) JoinEntryInstr(join_id, try_index);
|
||||
JoinEntryInstr* join = new (Z)
|
||||
JoinEntryInstr(join_id, try_index, Thread::Current()->GetNextDeoptId());
|
||||
|
||||
// The dominator set of the join is the intersection of the dominator
|
||||
// sets of all the predecessors. If we keep the dominator sets ordered
|
||||
@@ -460,7 +461,8 @@ Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
|
||||
GrowableArray<BlockEntryInstr*> join_dominators;
|
||||
for (intptr_t i = 0; i < num_exits; ++i) {
|
||||
// Add the control-flow edge.
|
||||
GotoInstr* goto_instr = new (Z) GotoInstr(join);
|
||||
GotoInstr* goto_instr =
|
||||
new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId());
|
||||
goto_instr->InheritDeoptTarget(zone(), ReturnAt(i));
|
||||
LastInstructionAt(i)->LinkTo(goto_instr);
|
||||
ExitBlockAt(i)->set_last_instruction(LastInstructionAt(i)->next());
|
||||
@@ -546,16 +548,19 @@ void InlineExitCollector::ReplaceCall(TargetEntryInstr* callee_entry) {
|
||||
// goes to the rest of the caller graph. It is removed as unreachable code
|
||||
// by the constant propagation.
|
||||
TargetEntryInstr* false_block = new (Z) TargetEntryInstr(
|
||||
caller_graph_->allocate_block_id(), call_block->try_index());
|
||||
caller_graph_->allocate_block_id(), call_block->try_index(),
|
||||
Thread::Current()->GetNextDeoptId());
|
||||
false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL);
|
||||
false_block->LinkTo(call_->next());
|
||||
call_block->ReplaceAsPredecessorWith(false_block);
|
||||
|
||||
ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True());
|
||||
BranchInstr* branch = new (Z) BranchInstr(new (Z) StrictCompareInstr(
|
||||
TokenPosition::kNoSource, Token::kEQ_STRICT, new (Z) Value(true_const),
|
||||
new (Z) Value(true_const),
|
||||
false)); // No number check.
|
||||
BranchInstr* branch = new (Z)
|
||||
BranchInstr(new (Z) StrictCompareInstr(
|
||||
TokenPosition::kNoSource, Token::kEQ_STRICT,
|
||||
new (Z) Value(true_const), new (Z) Value(true_const),
|
||||
false, Thread::Current()->GetNextDeoptId()),
|
||||
Thread::Current()->GetNextDeoptId()); // No number check.
|
||||
branch->InheritDeoptTarget(zone(), call_);
|
||||
*branch->true_successor_address() = callee_entry;
|
||||
*branch->false_successor_address() = false_block;
|
||||
@@ -699,7 +704,8 @@ void EffectGraphVisitor::AddInstruction(Instruction* instruction) {
|
||||
|
||||
void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, Value* value) {
|
||||
ASSERT(is_open());
|
||||
ReturnInstr* return_instr = new (Z) ReturnInstr(token_pos, value);
|
||||
ReturnInstr* return_instr =
|
||||
new (Z) ReturnInstr(token_pos, value, owner()->GetNextDeoptId());
|
||||
AddInstruction(return_instr);
|
||||
InlineExitCollector* exit_collector = owner()->exit_collector();
|
||||
if (exit_collector != NULL) {
|
||||
@@ -712,7 +718,7 @@ void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, Value* value) {
|
||||
void EffectGraphVisitor::Goto(JoinEntryInstr* join) {
|
||||
ASSERT(is_open());
|
||||
if (is_empty()) {
|
||||
entry_ = new (Z) GotoInstr(join);
|
||||
entry_ = new (Z) GotoInstr(join, owner()->GetNextDeoptId());
|
||||
} else {
|
||||
exit()->Goto(join);
|
||||
}
|
||||
@@ -761,8 +767,9 @@ void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment,
|
||||
} else if (false_exit == NULL) {
|
||||
exit_ = true_exit;
|
||||
} else {
|
||||
JoinEntryInstr* join = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr* join =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
true_exit->Goto(join);
|
||||
false_exit->Goto(join);
|
||||
exit_ = join;
|
||||
@@ -792,10 +799,11 @@ void EffectGraphVisitor::TieLoop(
|
||||
Append(test_preamble_fragment);
|
||||
Append(test_fragment);
|
||||
} else {
|
||||
JoinEntryInstr* join = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
CheckStackOverflowInstr* check =
|
||||
new (Z) CheckStackOverflowInstr(token_pos, owner()->loop_depth());
|
||||
JoinEntryInstr* join =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr(
|
||||
token_pos, owner()->loop_depth(), owner()->GetNextDeoptId());
|
||||
join->LinkTo(check);
|
||||
if (!test_preamble_fragment.is_empty()) {
|
||||
check->LinkTo(test_preamble_fragment.entry());
|
||||
@@ -929,7 +937,8 @@ void TestGraphVisitor::ConnectBranchesTo(
|
||||
ASSERT(!branches.is_empty());
|
||||
for (intptr_t i = 0; i < branches.length(); i++) {
|
||||
TargetEntryInstr* target = new (Z)
|
||||
TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
*(branches[i]) = target;
|
||||
target->Goto(join);
|
||||
}
|
||||
@@ -952,13 +961,15 @@ BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor(
|
||||
|
||||
if (branches.length() == 1) {
|
||||
TargetEntryInstr* target = new (Z)
|
||||
TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
*(branches[0]) = target;
|
||||
return target;
|
||||
}
|
||||
|
||||
JoinEntryInstr* join =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
ConnectBranchesTo(branches, join);
|
||||
return join;
|
||||
}
|
||||
@@ -977,13 +988,14 @@ BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const {
|
||||
void TestGraphVisitor::ReturnValue(Value* value) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
if (isolate->type_checks() || isolate->asserts()) {
|
||||
value = Bind(new (Z) AssertBooleanInstr(condition_token_pos(), value));
|
||||
value = Bind(new (Z) AssertBooleanInstr(condition_token_pos(), value,
|
||||
owner()->GetNextDeoptId()));
|
||||
}
|
||||
Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True()));
|
||||
StrictCompareInstr* comp = new (Z) StrictCompareInstr(
|
||||
condition_token_pos(), Token::kEQ_STRICT, value, constant_true,
|
||||
false); // No number check.
|
||||
BranchInstr* branch = new (Z) BranchInstr(comp);
|
||||
condition_token_pos(), Token::kEQ_STRICT, value, constant_true, false,
|
||||
owner()->GetNextDeoptId()); // No number check.
|
||||
BranchInstr* branch = new (Z) BranchInstr(comp, owner()->GetNextDeoptId());
|
||||
AddInstruction(branch);
|
||||
CloseFragment();
|
||||
|
||||
@@ -993,7 +1005,7 @@ void TestGraphVisitor::ReturnValue(Value* value) {
|
||||
|
||||
|
||||
void TestGraphVisitor::MergeBranchWithStrictCompare(StrictCompareInstr* comp) {
|
||||
BranchInstr* branch = new (Z) BranchInstr(comp);
|
||||
BranchInstr* branch = new (Z) BranchInstr(comp, owner()->GetNextDeoptId());
|
||||
AddInstruction(branch);
|
||||
CloseFragment();
|
||||
true_successor_addresses_.Add(branch->true_successor_address());
|
||||
@@ -1006,8 +1018,8 @@ void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) {
|
||||
Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True()));
|
||||
StrictCompareInstr* comp = new (Z) StrictCompareInstr(
|
||||
condition_token_pos(), Token::kNE_STRICT, neg->value(), constant_true,
|
||||
false); // No number check.
|
||||
BranchInstr* branch = new (Z) BranchInstr(comp);
|
||||
false, owner()->GetNextDeoptId()); // No number check.
|
||||
BranchInstr* branch = new (Z) BranchInstr(comp, owner()->GetNextDeoptId());
|
||||
AddInstruction(branch);
|
||||
CloseFragment();
|
||||
true_successor_addresses_.Add(branch->true_successor_address());
|
||||
@@ -1141,11 +1153,11 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
||||
ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
|
||||
const int kTypeArgsLen = 0;
|
||||
StaticCallInstr* call_async_clear_thread_stack_trace =
|
||||
new (Z) StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_clear_thread_stack_trace, kTypeArgsLen,
|
||||
Object::null_array(), no_arguments,
|
||||
owner()->ic_data_array());
|
||||
StaticCallInstr* call_async_clear_thread_stack_trace = new (Z)
|
||||
StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_clear_thread_stack_trace, kTypeArgsLen,
|
||||
Object::null_array(), no_arguments,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
Do(call_async_clear_thread_stack_trace);
|
||||
}
|
||||
|
||||
@@ -1180,7 +1192,8 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
||||
const int kTypeArgsLen = 0;
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos().ToSynthetic(), complete_on_async_return, kTypeArgsLen,
|
||||
Object::null_array(), arguments, owner()->ic_data_array());
|
||||
Object::null_array(), arguments, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId());
|
||||
Do(call);
|
||||
|
||||
// Rebind the return value for the actual return call to be null.
|
||||
@@ -1198,8 +1211,9 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
||||
if ((function.IsAsyncClosure() || function.IsSyncGenClosure() ||
|
||||
function.IsAsyncGenClosure()) &&
|
||||
(node->return_type() == ReturnNode::kContinuationTarget)) {
|
||||
JoinEntryInstr* const join = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr* const join =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
owner()->await_joins()->Add(join);
|
||||
exit_ = join;
|
||||
}
|
||||
@@ -1242,7 +1256,8 @@ void ValueGraphVisitor::VisitTypeNode(TypeNode* node) {
|
||||
function_type_arguments = BuildFunctionTypeArguments(token_pos);
|
||||
}
|
||||
ReturnDefinition(new (Z) InstantiateTypeInstr(
|
||||
token_pos, type, instantiator_type_arguments, function_type_arguments));
|
||||
token_pos, type, instantiator_type_arguments, function_type_arguments,
|
||||
owner()->GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1332,8 +1347,8 @@ void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
||||
ValueGraphVisitor for_right(owner());
|
||||
node->right()->Visit(&for_right);
|
||||
Value* right_value = for_right.value();
|
||||
for_right.Do(
|
||||
new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value));
|
||||
for_right.Do(new (Z) AssertBooleanInstr(
|
||||
node->right()->token_pos(), right_value, owner()->GetNextDeoptId()));
|
||||
if (node->kind() == Token::kAND) {
|
||||
Join(for_left, for_right, empty);
|
||||
} else {
|
||||
@@ -1368,9 +1383,10 @@ void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
||||
const String& name = Symbols::Token(node->kind());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 2;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), name, node->kind(), arguments, kTypeArgsLen,
|
||||
Object::null_array(), kNumArgsChecked, owner()->ic_data_array());
|
||||
InstanceCallInstr* call = new (Z)
|
||||
InstanceCallInstr(node->token_pos(), name, node->kind(), arguments,
|
||||
kTypeArgsLen, Object::null_array(), kNumArgsChecked,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
@@ -1393,13 +1409,13 @@ void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
||||
Value* right_value = for_right.value();
|
||||
Isolate* isolate = Isolate::Current();
|
||||
if (isolate->type_checks() || isolate->asserts()) {
|
||||
right_value = for_right.Bind(
|
||||
new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value));
|
||||
right_value = for_right.Bind(new (Z) AssertBooleanInstr(
|
||||
node->right()->token_pos(), right_value, owner()->GetNextDeoptId()));
|
||||
}
|
||||
Value* constant_true = for_right.Bind(new (Z) ConstantInstr(Bool::True()));
|
||||
Value* compare = for_right.Bind(new (Z) StrictCompareInstr(
|
||||
node->token_pos(), Token::kEQ_STRICT, right_value, constant_true,
|
||||
false)); // No number check.
|
||||
node->token_pos(), Token::kEQ_STRICT, right_value, constant_true, false,
|
||||
owner()->GetNextDeoptId())); // No number check.
|
||||
for_right.Do(BuildStoreExprTemp(compare, node->token_pos()));
|
||||
|
||||
if (node->kind() == Token::kAND) {
|
||||
@@ -1535,7 +1551,7 @@ void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
|
||||
Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), node->kind(),
|
||||
arguments, kTypeArgsLen,
|
||||
Object::null_array(), // No argument names.
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
if (negate_result) {
|
||||
result = new (Z) BooleanNegateInstr(Bind(result));
|
||||
}
|
||||
@@ -1560,7 +1576,7 @@ void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
|
||||
node->token_pos(), Library::PrivateCoreLibName(Symbols::_instanceOf()),
|
||||
node->kind(), arguments, kTypeArgsLen,
|
||||
Object::null_array(), // No argument names.
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
if (negate_result) {
|
||||
result = new (Z) BooleanNegateInstr(Bind(result));
|
||||
}
|
||||
@@ -1599,7 +1615,7 @@ void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
|
||||
node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()),
|
||||
node->kind(), arguments, kTypeArgsLen,
|
||||
Object::null_array(), // No argument names.
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
@@ -1616,8 +1632,8 @@ StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare(
|
||||
right->Visit(&for_right_value);
|
||||
Append(for_right_value);
|
||||
StrictCompareInstr* comp = new (Z) StrictCompareInstr(
|
||||
token_pos, kind, for_left_value.value(), for_right_value.value(),
|
||||
true); // Number check.
|
||||
token_pos, kind, for_left_value.value(), for_right_value.value(), true,
|
||||
owner()->GetNextDeoptId()); // Number check.
|
||||
return comp;
|
||||
}
|
||||
|
||||
@@ -1673,16 +1689,17 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 2;
|
||||
Definition* result = new (Z)
|
||||
InstanceCallInstr(node->token_pos(), Symbols::EqualOperator(),
|
||||
Token::kEQ, // Result is negated later for kNE.
|
||||
arguments, kTypeArgsLen, Object::null_array(),
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
Definition* result = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::EqualOperator(),
|
||||
Token::kEQ, // Result is negated later for kNE.
|
||||
arguments, kTypeArgsLen, Object::null_array(), kNumArgsChecked,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
if (node->kind() == Token::kNE) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
if (isolate->type_checks() || isolate->asserts()) {
|
||||
Value* value = Bind(result);
|
||||
result = new (Z) AssertBooleanInstr(node->token_pos(), value);
|
||||
result = new (Z) AssertBooleanInstr(node->token_pos(), value,
|
||||
owner()->GetNextDeoptId());
|
||||
}
|
||||
Value* value = Bind(result);
|
||||
result = new (Z) BooleanNegateInstr(value);
|
||||
@@ -1710,7 +1727,8 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
InstanceCallInstr* comp = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments,
|
||||
kTypeArgsLen, Object::null_array(), 2, owner()->ic_data_array());
|
||||
kTypeArgsLen, Object::null_array(), 2, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId());
|
||||
ReturnDefinition(comp);
|
||||
}
|
||||
|
||||
@@ -1724,8 +1742,8 @@ void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) {
|
||||
Value* value = for_value.value();
|
||||
Isolate* isolate = Isolate::Current();
|
||||
if (isolate->type_checks() || isolate->asserts()) {
|
||||
value =
|
||||
Bind(new (Z) AssertBooleanInstr(node->operand()->token_pos(), value));
|
||||
value = Bind(new (Z) AssertBooleanInstr(
|
||||
node->operand()->token_pos(), value, owner()->GetNextDeoptId()));
|
||||
}
|
||||
BooleanNegateInstr* negate = new (Z) BooleanNegateInstr(value);
|
||||
ReturnDefinition(negate);
|
||||
@@ -1742,7 +1760,8 @@ void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments,
|
||||
kTypeArgsLen, Object::null_array(), 1, owner()->ic_data_array());
|
||||
kTypeArgsLen, Object::null_array(), 1, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
@@ -1840,8 +1859,9 @@ void EffectGraphVisitor::VisitCaseNode(CaseNode* node) {
|
||||
// Compute the start of the statements fragment.
|
||||
JoinEntryInstr* statement_start = NULL;
|
||||
if (node->label() == NULL) {
|
||||
statement_start = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
statement_start =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
} else {
|
||||
// The case nodes are nested inside a SequenceNode that is the body of a
|
||||
// SwitchNode. The SwitchNode on the nesting stack contains the
|
||||
@@ -1893,7 +1913,8 @@ void EffectGraphVisitor::VisitCaseNode(CaseNode* node) {
|
||||
} else {
|
||||
if (statement_exit != NULL) {
|
||||
JoinEntryInstr* join = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
statement_exit->Goto(join);
|
||||
next_target->Goto(join);
|
||||
exit_instruction = join;
|
||||
@@ -1976,7 +1997,8 @@ void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
|
||||
|
||||
// Tie do-while loop (test is after the body).
|
||||
JoinEntryInstr* body_entry_join =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
Goto(body_entry_join);
|
||||
Instruction* body_exit = AppendFragment(body_entry_join, for_body);
|
||||
|
||||
@@ -1984,10 +2006,11 @@ void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
|
||||
if ((body_exit != NULL) || (join != NULL)) {
|
||||
if (join == NULL) {
|
||||
join = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
}
|
||||
CheckStackOverflowInstr* check = new (Z)
|
||||
CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth());
|
||||
CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr(
|
||||
node->token_pos(), owner()->loop_depth(), owner()->GetNextDeoptId());
|
||||
join->LinkTo(check);
|
||||
check->LinkTo(for_test.entry());
|
||||
if (body_exit != NULL) {
|
||||
@@ -2035,8 +2058,9 @@ void EffectGraphVisitor::VisitForNode(ForNode* node) {
|
||||
// Join the loop body and increment and then tie the loop.
|
||||
JoinEntryInstr* continue_join = nested_loop.continue_target();
|
||||
if ((continue_join != NULL) || for_body.is_open()) {
|
||||
JoinEntryInstr* loop_entry = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr* loop_entry =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
if (continue_join != NULL) {
|
||||
if (for_body.is_open()) for_body.Goto(continue_join);
|
||||
Instruction* current = AppendFragment(continue_join, for_increment);
|
||||
@@ -2053,7 +2077,8 @@ void EffectGraphVisitor::VisitForNode(ForNode* node) {
|
||||
// the context level (if any) matches the that of the increment
|
||||
// expression.
|
||||
AddInstruction(new (Z) CheckStackOverflowInstr(
|
||||
node->increment()->token_pos(), owner()->loop_depth()));
|
||||
node->increment()->token_pos(), owner()->loop_depth(),
|
||||
owner()->GetNextDeoptId()));
|
||||
}
|
||||
|
||||
if (node->condition() == NULL) {
|
||||
@@ -2248,8 +2273,8 @@ void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
|
||||
BuildInstantiatedTypeArguments(node->token_pos(), type_args);
|
||||
Value* num_elements =
|
||||
Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(node->length()))));
|
||||
CreateArrayInstr* create =
|
||||
new (Z) CreateArrayInstr(node->token_pos(), element_type, num_elements);
|
||||
CreateArrayInstr* create = new (Z) CreateArrayInstr(
|
||||
node->token_pos(), element_type, num_elements, owner()->GetNextDeoptId());
|
||||
Value* array_val = Bind(create);
|
||||
|
||||
{
|
||||
@@ -2299,16 +2324,16 @@ void EffectGraphVisitor::VisitStringInterpolateNode(
|
||||
Z, Resolver::ResolveStatic(
|
||||
cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()),
|
||||
kTypeArgsLen, kNumberOfArguments, kNoArgumentNames));
|
||||
StaticCallInstr* call = new (Z)
|
||||
StaticCallInstr(node->token_pos(), function, kTypeArgsLen,
|
||||
kNoArgumentNames, values, owner()->ic_data_array());
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos(), function, kTypeArgsLen, kNoArgumentNames, values,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
return;
|
||||
}
|
||||
arguments->Visit(&for_argument);
|
||||
Append(for_argument);
|
||||
StringInterpolateInstr* instr =
|
||||
new (Z) StringInterpolateInstr(for_argument.value(), node->token_pos());
|
||||
StringInterpolateInstr* instr = new (Z) StringInterpolateInstr(
|
||||
for_argument.value(), node->token_pos(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(instr);
|
||||
}
|
||||
|
||||
@@ -2530,7 +2555,7 @@ void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), node->function_name(), Token::kILLEGAL, arguments,
|
||||
node->arguments()->type_args_len(), node->arguments()->names(), 1,
|
||||
owner()->ic_data_array());
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
}
|
||||
@@ -2546,7 +2571,8 @@ void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos(), node->function(), node->arguments()->type_args_len(),
|
||||
node->arguments()->names(), arguments, owner()->ic_data_array());
|
||||
node->arguments()->names(), arguments, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId());
|
||||
if (node->function().recognized_kind() != MethodRecognizer::kUnknown) {
|
||||
call->set_result_cid(MethodRecognizer::ResultCid(node->function()));
|
||||
}
|
||||
@@ -2580,8 +2606,8 @@ void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node,
|
||||
function_load->set_is_immutable(true);
|
||||
Value* function_val = Bind(function_load);
|
||||
|
||||
Definition* closure_call =
|
||||
new (Z) ClosureCallInstr(function_val, node, arguments);
|
||||
Definition* closure_call = new (Z) ClosureCallInstr(
|
||||
function_val, node, arguments, owner()->GetNextDeoptId());
|
||||
if (result_needed) {
|
||||
Value* result = Bind(closure_call);
|
||||
Do(new (Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos())));
|
||||
@@ -2605,13 +2631,15 @@ void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) {
|
||||
void EffectGraphVisitor::VisitInitStaticFieldNode(InitStaticFieldNode* node) {
|
||||
Value* field = Bind(
|
||||
new (Z) ConstantInstr(Field::ZoneHandle(Z, node->field().Original())));
|
||||
AddInstruction(new (Z) InitStaticFieldInstr(field, node->field()));
|
||||
AddInstruction(new (Z) InitStaticFieldInstr(field, node->field(),
|
||||
owner()->GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) {
|
||||
Value* context = Bind(BuildCurrentContext(node->token_pos()));
|
||||
Value* clone = Bind(new (Z) CloneContextInstr(node->token_pos(), context));
|
||||
Value* clone = Bind(new (Z) CloneContextInstr(node->token_pos(), context,
|
||||
owner()->GetNextDeoptId()));
|
||||
Do(BuildStoreContext(clone, node->token_pos()));
|
||||
}
|
||||
|
||||
@@ -2645,9 +2673,10 @@ void EffectGraphVisitor::BuildConstructorCall(
|
||||
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
Do(new (Z) StaticCallInstr(node->token_pos(), node->constructor(),
|
||||
kTypeArgsLen, node->arguments()->names(),
|
||||
arguments, owner()->ic_data_array()));
|
||||
Do(new (Z)
|
||||
StaticCallInstr(node->token_pos(), node->constructor(), kTypeArgsLen,
|
||||
node->arguments()->names(), arguments,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -2686,9 +2715,10 @@ void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
|
||||
ASSERT(arguments->length() == 1);
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
const int kTypeArgsLen = 0;
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos(), node->constructor(), kTypeArgsLen,
|
||||
node->arguments()->names(), arguments, owner()->ic_data_array());
|
||||
StaticCallInstr* call = new (Z)
|
||||
StaticCallInstr(node->token_pos(), node->constructor(), kTypeArgsLen,
|
||||
node->arguments()->names(), arguments,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
const intptr_t result_cid = GetResultCidOfListFactory(node);
|
||||
if (result_cid != kDynamicCid) {
|
||||
call->set_result_cid(result_cid);
|
||||
@@ -2830,7 +2860,7 @@ Value* EffectGraphVisitor::BuildInstantiatedTypeArguments(
|
||||
}
|
||||
return Bind(new (Z) InstantiateTypeArgumentsInstr(
|
||||
token_pos, type_arguments, instantiator_class, instantiator_type_args,
|
||||
function_type_args));
|
||||
function_type_args, owner()->GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -2919,9 +2949,10 @@ void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
|
||||
const String& name =
|
||||
String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), name, Token::kGET, arguments, kTypeArgsLen,
|
||||
Object::null_array(), 1, owner()->ic_data_array());
|
||||
InstanceCallInstr* call = new (Z)
|
||||
InstanceCallInstr(node->token_pos(), name, Token::kGET, arguments,
|
||||
kTypeArgsLen, Object::null_array(), 1,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
}
|
||||
@@ -2983,9 +3014,10 @@ void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
|
||||
String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
|
||||
const int kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 1; // Do not check value type.
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
token_pos, name, Token::kSET, arguments, kTypeArgsLen,
|
||||
Object::null_array(), kNumArgsChecked, owner()->ic_data_array());
|
||||
InstanceCallInstr* call = new (Z)
|
||||
InstanceCallInstr(token_pos, name, Token::kSET, arguments, kTypeArgsLen,
|
||||
Object::null_array(), kNumArgsChecked,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
@@ -3030,7 +3062,8 @@ void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
|
||||
const intptr_t kNumArgsChecked = 1; // Do not check value type.
|
||||
Do(new (Z) InstanceCallInstr(token_pos, name, Token::kSET, arguments,
|
||||
kTypeArgsLen, Object::null_array(),
|
||||
kNumArgsChecked, owner()->ic_data_array()));
|
||||
kNumArgsChecked, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId()));
|
||||
ReturnDefinition(BuildLoadExprTemp(token_pos));
|
||||
}
|
||||
|
||||
@@ -3093,10 +3126,10 @@ void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) {
|
||||
}
|
||||
ASSERT(!getter_function.IsNull());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* call =
|
||||
new (Z) StaticCallInstr(node->token_pos(), getter_function, kTypeArgsLen,
|
||||
Object::null_array(), // No names
|
||||
arguments, owner()->ic_data_array());
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos(), getter_function, kTypeArgsLen,
|
||||
Object::null_array(), // No names
|
||||
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
@@ -3158,7 +3191,8 @@ void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node,
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
call = new (Z) StaticCallInstr(token_pos, setter_function, kTypeArgsLen,
|
||||
Object::null_array(), // No names.
|
||||
arguments, owner()->ic_data_array());
|
||||
arguments, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId());
|
||||
}
|
||||
if (result_is_needed) {
|
||||
Do(call);
|
||||
@@ -3250,8 +3284,9 @@ void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
|
||||
Value* other = Bind(new (Z) LoadLocalInstr(*other_var, token_pos));
|
||||
// Receiver is not a number because numbers override equality.
|
||||
const bool kNoNumberCheck = false;
|
||||
StrictCompareInstr* compare = new (Z) StrictCompareInstr(
|
||||
token_pos, Token::kEQ_STRICT, receiver, other, kNoNumberCheck);
|
||||
StrictCompareInstr* compare = new (Z)
|
||||
StrictCompareInstr(token_pos, Token::kEQ_STRICT, receiver, other,
|
||||
kNoNumberCheck, owner()->GetNextDeoptId());
|
||||
return ReturnDefinition(compare);
|
||||
}
|
||||
case MethodRecognizer::kStringBaseLength:
|
||||
@@ -3271,9 +3306,9 @@ void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
|
||||
Value* zero_val =
|
||||
Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(0))));
|
||||
Value* load_val = Bind(load);
|
||||
StrictCompareInstr* compare = new (Z)
|
||||
StrictCompareInstr(token_pos, Token::kEQ_STRICT, load_val, zero_val,
|
||||
false); // No number check.
|
||||
StrictCompareInstr* compare = new (Z) StrictCompareInstr(
|
||||
token_pos, Token::kEQ_STRICT, load_val, zero_val, false,
|
||||
owner()->GetNextDeoptId()); // No number check.
|
||||
return ReturnDefinition(compare);
|
||||
}
|
||||
case MethodRecognizer::kGrowableArrayLength:
|
||||
@@ -3316,8 +3351,8 @@ void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
|
||||
node->scope()->LookupVariable(Symbols::Length(), true);
|
||||
Value* length =
|
||||
Bind(new (Z) LoadLocalInstr(*length_parameter, token_pos));
|
||||
CreateArrayInstr* create_array =
|
||||
new CreateArrayInstr(token_pos, element_type, length);
|
||||
CreateArrayInstr* create_array = new CreateArrayInstr(
|
||||
token_pos, element_type, length, owner()->GetNextDeoptId());
|
||||
return ReturnDefinition(create_array);
|
||||
}
|
||||
case MethodRecognizer::kBigint_getDigits: {
|
||||
@@ -3607,7 +3642,7 @@ void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
|
||||
// Generate static call to super operator.
|
||||
StaticCallInstr* load = new (Z) StaticCallInstr(
|
||||
node->token_pos(), *super_function, kTypeArgsLen, Object::null_array(),
|
||||
arguments, owner()->ic_data_array());
|
||||
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(load);
|
||||
} else {
|
||||
// Generate dynamic call to index operator.
|
||||
@@ -3615,7 +3650,7 @@ void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
|
||||
InstanceCallInstr* load = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::IndexToken(), Token::kINDEX, arguments,
|
||||
kTypeArgsLen, Object::null_array(), checked_argument_count,
|
||||
owner()->ic_data_array());
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
ReturnDefinition(load);
|
||||
}
|
||||
}
|
||||
@@ -3681,7 +3716,7 @@ Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node,
|
||||
|
||||
StaticCallInstr* store = new (Z) StaticCallInstr(
|
||||
token_pos, *super_function, kTypeArgsLen, Object::null_array(),
|
||||
arguments, owner()->ic_data_array());
|
||||
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
if (result_is_needed) {
|
||||
Do(store);
|
||||
return BuildLoadExprTemp(token_pos);
|
||||
@@ -3694,7 +3729,7 @@ Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node,
|
||||
InstanceCallInstr* store = new (Z) InstanceCallInstr(
|
||||
token_pos, Symbols::AssignIndexToken(), Token::kASSIGN_INDEX, arguments,
|
||||
kTypeArgsLen, Object::null_array(), checked_argument_count,
|
||||
owner()->ic_data_array());
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
if (result_is_needed) {
|
||||
Do(store);
|
||||
return BuildLoadExprTemp(token_pos);
|
||||
@@ -3865,11 +3900,11 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
||||
ASSERT(!async_set_thread_stack_trace.IsNull());
|
||||
// Call _asyncSetThreadStackTrace
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* call_async_set_thread_stack_trace =
|
||||
new (Z) StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_set_thread_stack_trace, kTypeArgsLen,
|
||||
Object::null_array(), arguments,
|
||||
owner()->ic_data_array());
|
||||
StaticCallInstr* call_async_set_thread_stack_trace = new (Z)
|
||||
StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_set_thread_stack_trace, kTypeArgsLen,
|
||||
Object::null_array(), arguments,
|
||||
owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
Do(call_async_set_thread_stack_trace);
|
||||
}
|
||||
|
||||
@@ -3903,8 +3938,8 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
||||
// if we inline or not.
|
||||
if (!function.IsImplicitGetterFunction() &&
|
||||
!function.IsImplicitSetterFunction()) {
|
||||
CheckStackOverflowInstr* check =
|
||||
new (Z) CheckStackOverflowInstr(node->token_pos(), 0);
|
||||
CheckStackOverflowInstr* check = new (Z) CheckStackOverflowInstr(
|
||||
node->token_pos(), 0, owner()->GetNextDeoptId());
|
||||
// If we are inlining don't actually attach the stack check. We must still
|
||||
// create the stack check in order to allocate a deopt id.
|
||||
if (!owner()->IsInlining()) {
|
||||
@@ -3944,8 +3979,9 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
||||
if (is_top_level_sequence &&
|
||||
(function.IsAsyncClosure() || function.IsSyncGenClosure() ||
|
||||
function.IsAsyncGenClosure())) {
|
||||
JoinEntryInstr* preamble_end = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr* preamble_end =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
ASSERT(exit() != NULL);
|
||||
exit()->Goto(preamble_end);
|
||||
ASSERT(exit()->next()->IsGoto());
|
||||
@@ -4087,13 +4123,14 @@ void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
|
||||
|
||||
if (for_try.is_open()) {
|
||||
JoinEntryInstr* after_try = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index);
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index,
|
||||
owner()->GetNextDeoptId());
|
||||
for_try.Goto(after_try);
|
||||
for_try.exit_ = after_try;
|
||||
}
|
||||
|
||||
JoinEntryInstr* try_entry =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index);
|
||||
JoinEntryInstr* try_entry = new (Z) JoinEntryInstr(
|
||||
owner()->AllocateBlockId(), try_handler_index, owner()->GetNextDeoptId());
|
||||
|
||||
Goto(try_entry);
|
||||
AppendFragment(try_entry, for_try);
|
||||
@@ -4133,7 +4170,8 @@ void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
|
||||
|
||||
if (for_catch.is_open()) {
|
||||
JoinEntryInstr* join = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index);
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index,
|
||||
owner()->GetNextDeoptId());
|
||||
for_catch.Goto(join);
|
||||
if (is_open()) Goto(join);
|
||||
exit_ = join;
|
||||
@@ -4158,7 +4196,8 @@ void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
|
||||
catch_block->rethrow_stacktrace_var(), finally_block->token_pos()));
|
||||
for_finally.PushArgument(stacktrace);
|
||||
for_finally.AddInstruction(
|
||||
new (Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index));
|
||||
new (Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index,
|
||||
owner()->GetNextDeoptId()));
|
||||
for_finally.CloseFragment();
|
||||
}
|
||||
ASSERT(!for_finally.is_open());
|
||||
@@ -4221,9 +4260,9 @@ StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall(
|
||||
ZoneGrowableArray<PushArgumentInstr*>* push_arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
|
||||
BuildPushArguments(*args, push_arguments);
|
||||
return new (Z) StaticCallInstr(args_pos, no_such_method_func, kTypeArgsLen,
|
||||
Object::null_array(), push_arguments,
|
||||
owner()->ic_data_array());
|
||||
return new (Z) StaticCallInstr(
|
||||
args_pos, no_such_method_func, kTypeArgsLen, Object::null_array(),
|
||||
push_arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
@@ -4289,7 +4328,8 @@ StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError(
|
||||
ASSERT(!func.IsNull());
|
||||
return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen,
|
||||
Object::null_array(), // No names.
|
||||
arguments, owner()->ic_data_array());
|
||||
arguments, owner()->ic_data_array(),
|
||||
owner()->GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
@@ -4309,13 +4349,14 @@ void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) {
|
||||
PushArgument(for_exception.value());
|
||||
Instruction* instr = NULL;
|
||||
if (node->stacktrace() == NULL) {
|
||||
instr = new (Z) ThrowInstr(node->token_pos());
|
||||
instr = new (Z) ThrowInstr(node->token_pos(), owner()->GetNextDeoptId());
|
||||
} else {
|
||||
ValueGraphVisitor for_stack_trace(owner());
|
||||
node->stacktrace()->Visit(&for_stack_trace);
|
||||
Append(for_stack_trace);
|
||||
PushArgument(for_stack_trace.value());
|
||||
instr = new (Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index());
|
||||
instr = new (Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
}
|
||||
AddInstruction(instr);
|
||||
}
|
||||
@@ -4355,7 +4396,8 @@ void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) {
|
||||
// context variable.
|
||||
|
||||
JoinEntryInstr* finally_entry =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
EffectGraphVisitor for_finally_block(owner());
|
||||
for_finally_block.AdjustContextLevel(node->finally_block()->scope());
|
||||
node->finally_block()->Visit(&for_finally_block);
|
||||
@@ -4365,8 +4407,9 @@ void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) {
|
||||
}
|
||||
|
||||
if (for_finally_block.is_open()) {
|
||||
JoinEntryInstr* after_finally = new (Z)
|
||||
JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
|
||||
JoinEntryInstr* after_finally =
|
||||
new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index(),
|
||||
owner()->GetNextDeoptId());
|
||||
for_finally_block.Goto(after_finally);
|
||||
for_finally_block.exit_ = after_finally;
|
||||
}
|
||||
@@ -4396,8 +4439,8 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
|
||||
AstPrinter ast_printer;
|
||||
ast_printer.PrintFunctionScope(parsed_function());
|
||||
}
|
||||
TargetEntryInstr* normal_entry = new (Z)
|
||||
TargetEntryInstr(AllocateBlockId(), CatchClauseNode::kInvalidTryIndex);
|
||||
TargetEntryInstr* normal_entry = new (Z) TargetEntryInstr(
|
||||
AllocateBlockId(), CatchClauseNode::kInvalidTryIndex, GetNextDeoptId());
|
||||
graph_entry_ =
|
||||
new (Z) GraphEntryInstr(parsed_function(), normal_entry, osr_id_);
|
||||
EffectGraphVisitor for_effect(this);
|
||||
|
||||
@@ -114,6 +114,11 @@ class FlowGraphBuilder : public ValueObject {
|
||||
intptr_t AllocateBlockId() { return ++last_used_block_id_; }
|
||||
void SetInitialBlockId(intptr_t id) { last_used_block_id_ = id; }
|
||||
|
||||
intptr_t GetNextDeoptId() {
|
||||
// TODO(rmacnak): Record current scope / context level.
|
||||
return thread()->GetNextDeoptId();
|
||||
}
|
||||
|
||||
intptr_t context_level() const;
|
||||
|
||||
void IncrementLoopDepth() { ++loop_depth_; }
|
||||
|
||||
@@ -1480,10 +1480,10 @@ bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
|
||||
new_join->AddDominatedBlock(block);
|
||||
}
|
||||
// Create a new target with the join as unconditional successor.
|
||||
TargetEntryInstr* new_target =
|
||||
new TargetEntryInstr(AllocateBlockId(), old_target->try_index());
|
||||
TargetEntryInstr* new_target = new TargetEntryInstr(
|
||||
AllocateBlockId(), old_target->try_index(), Thread::kNoDeoptId);
|
||||
new_target->InheritDeoptTarget(zone(), new_join);
|
||||
GotoInstr* new_goto = new (Z) GotoInstr(new_join);
|
||||
GotoInstr* new_goto = new (Z) GotoInstr(new_join, Thread::kNoDeoptId);
|
||||
new_goto->InheritDeoptTarget(zone(), new_join);
|
||||
new_target->LinkTo(new_goto);
|
||||
new_target->set_last_instruction(new_goto);
|
||||
@@ -1622,8 +1622,9 @@ bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid,
|
||||
InlineExitCollector* exit_collector =
|
||||
new (Z) InlineExitCollector(owner_->caller_graph(), call_);
|
||||
|
||||
ReturnInstr* result = new (Z)
|
||||
ReturnInstr(call_->instance_call()->token_pos(), new (Z) Value(last));
|
||||
ReturnInstr* result =
|
||||
new (Z) ReturnInstr(call_->instance_call()->token_pos(),
|
||||
new (Z) Value(last), Thread::kNoDeoptId);
|
||||
owner_->caller_graph()->AppendTo(
|
||||
last, result,
|
||||
call_->env(), // Return can become deoptimization target.
|
||||
@@ -1653,8 +1654,8 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
const intptr_t try_idx = call_->GetBlock()->try_index();
|
||||
|
||||
// Start with a fresh target entry.
|
||||
TargetEntryInstr* entry =
|
||||
new (Z) TargetEntryInstr(AllocateBlockId(), try_idx);
|
||||
TargetEntryInstr* entry = new (Z) TargetEntryInstr(
|
||||
AllocateBlockId(), try_idx, Thread::Current()->GetNextDeoptId());
|
||||
entry->InheritDeoptTarget(zone(), call_);
|
||||
|
||||
// This function uses a cursor (a pointer to the 'current' instruction) to
|
||||
@@ -1719,7 +1720,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
// the join.
|
||||
JoinEntryInstr* join = callee_entry->AsJoinEntry();
|
||||
ASSERT(join->dominator() != NULL);
|
||||
GotoInstr* goto_join = new GotoInstr(join);
|
||||
GotoInstr* goto_join = new GotoInstr(join, Thread::kNoDeoptId);
|
||||
goto_join->InheritDeoptTarget(zone(), join);
|
||||
cursor->LinkTo(goto_join);
|
||||
current_block->set_last_instruction(goto_join);
|
||||
@@ -1749,13 +1750,13 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
new Value(load_cid), new Value(cid_constant_end), kSmiCid,
|
||||
call_->deopt_id());
|
||||
BranchInstr* branch_top = upper_limit_branch =
|
||||
new BranchInstr(compare_top);
|
||||
new BranchInstr(compare_top, Thread::kNoDeoptId);
|
||||
branch_top->InheritDeoptTarget(zone(), call_);
|
||||
cursor = AppendInstruction(cursor, branch_top);
|
||||
current_block->set_last_instruction(branch_top);
|
||||
|
||||
TargetEntryInstr* below_target =
|
||||
new TargetEntryInstr(AllocateBlockId(), try_idx);
|
||||
TargetEntryInstr* below_target = new TargetEntryInstr(
|
||||
AllocateBlockId(), try_idx, Thread::kNoDeoptId);
|
||||
below_target->InheritDeoptTarget(zone(), call_);
|
||||
current_block->AddDominatedBlock(below_target);
|
||||
cursor = current_block = below_target;
|
||||
@@ -1765,13 +1766,13 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
call_->instance_call()->token_pos(), Token::kGTE,
|
||||
new Value(load_cid), new Value(cid_constant), kSmiCid,
|
||||
call_->deopt_id());
|
||||
branch = new BranchInstr(compare_bottom);
|
||||
branch = new BranchInstr(compare_bottom, Thread::kNoDeoptId);
|
||||
} else {
|
||||
StrictCompareInstr* compare = new StrictCompareInstr(
|
||||
call_->instance_call()->token_pos(), Token::kEQ_STRICT,
|
||||
new Value(load_cid), new Value(cid_constant),
|
||||
false); // No number check.
|
||||
branch = new BranchInstr(compare);
|
||||
/* number_check = */ false, Thread::kNoDeoptId);
|
||||
branch = new BranchInstr(compare, Thread::kNoDeoptId);
|
||||
}
|
||||
|
||||
branch->InheritDeoptTarget(zone(), call_);
|
||||
@@ -1802,9 +1803,10 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
JoinEntryInstr* join = callee_entry->AsJoinEntry();
|
||||
ASSERT(join != NULL);
|
||||
ASSERT(join->dominator() != NULL);
|
||||
true_target = new TargetEntryInstr(AllocateBlockId(), try_idx);
|
||||
true_target = new TargetEntryInstr(AllocateBlockId(), try_idx,
|
||||
Thread::kNoDeoptId);
|
||||
true_target->InheritDeoptTarget(zone(), join);
|
||||
GotoInstr* goto_join = new GotoInstr(join);
|
||||
GotoInstr* goto_join = new GotoInstr(join, Thread::kNoDeoptId);
|
||||
goto_join->InheritDeoptTarget(zone(), join);
|
||||
true_target->LinkTo(goto_join);
|
||||
true_target->set_last_instruction(goto_join);
|
||||
@@ -1816,7 +1818,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
// fall-through code below for non-inlined variants.
|
||||
|
||||
TargetEntryInstr* false_target =
|
||||
new TargetEntryInstr(AllocateBlockId(), try_idx);
|
||||
new TargetEntryInstr(AllocateBlockId(), try_idx, Thread::kNoDeoptId);
|
||||
false_target->InheritDeoptTarget(zone(), call_);
|
||||
*branch->false_successor_address() = false_target;
|
||||
cid_test_entry_block->AddDominatedBlock(false_target);
|
||||
@@ -1826,14 +1828,15 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
if (test_is_range) {
|
||||
// If we tested against a range of Cids there are two different tests
|
||||
// that can go to the no-cid-match target.
|
||||
JoinEntryInstr* join = new JoinEntryInstr(AllocateBlockId(), try_idx);
|
||||
TargetEntryInstr* false_target2 =
|
||||
new TargetEntryInstr(AllocateBlockId(), try_idx);
|
||||
JoinEntryInstr* join =
|
||||
new JoinEntryInstr(AllocateBlockId(), try_idx, Thread::kNoDeoptId);
|
||||
TargetEntryInstr* false_target2 = new TargetEntryInstr(
|
||||
AllocateBlockId(), try_idx, Thread::kNoDeoptId);
|
||||
*upper_limit_branch->false_successor_address() = false_target2;
|
||||
cid_test_entry_block->AddDominatedBlock(false_target2);
|
||||
cid_test_entry_block->AddDominatedBlock(join);
|
||||
GotoInstr* goto_1 = new GotoInstr(join);
|
||||
GotoInstr* goto_2 = new GotoInstr(join);
|
||||
GotoInstr* goto_1 = new GotoInstr(join, Thread::kNoDeoptId);
|
||||
GotoInstr* goto_2 = new GotoInstr(join, Thread::kNoDeoptId);
|
||||
false_target->LinkTo(goto_1);
|
||||
false_target2->LinkTo(goto_2);
|
||||
false_target->set_last_instruction(goto_1);
|
||||
@@ -1866,8 +1869,9 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
owner_->caller_graph()->alloc_ssa_temp_index());
|
||||
fallback_call->InheritDeoptTarget(zone(), call_);
|
||||
fallback_call->set_total_call_count(call_->CallCount());
|
||||
ReturnInstr* fallback_return = new ReturnInstr(
|
||||
call_->instance_call()->token_pos(), new Value(fallback_call));
|
||||
ReturnInstr* fallback_return =
|
||||
new ReturnInstr(call_->instance_call()->token_pos(),
|
||||
new Value(fallback_call), Thread::kNoDeoptId);
|
||||
fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_,
|
||||
fallback_call);
|
||||
AppendInstruction(AppendInstruction(cursor, fallback_call),
|
||||
@@ -2243,8 +2247,9 @@ static bool InlineGetIndexed(FlowGraph* flow_graph,
|
||||
|
||||
Definition* array = receiver;
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
|
||||
@@ -2292,8 +2297,9 @@ static bool InlineSetIndexed(FlowGraph* flow_graph,
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
Definition* stored_value = call->ArgumentAt(2);
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
if (flow_graph->isolate()->type_checks()) {
|
||||
@@ -2429,8 +2435,9 @@ static bool InlineDoubleOp(FlowGraph* flow_graph,
|
||||
Definition* left = receiver;
|
||||
Definition* right = call->ArgumentAt(1);
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
// Arguments are checked. No need for class check.
|
||||
BinaryDoubleOpInstr* double_bin_op = new (Z)
|
||||
@@ -2453,8 +2460,9 @@ static bool InlineDoubleTestOp(FlowGraph* flow_graph,
|
||||
return false;
|
||||
}
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
// Arguments are checked. No need for class check.
|
||||
|
||||
@@ -2475,8 +2483,9 @@ static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph,
|
||||
Definition* left = receiver;
|
||||
Definition* right = call->ArgumentAt(1);
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
// Right arguments is known to be smi: other._bitAndFromSmi(this);
|
||||
BinarySmiOpInstr* smi_op =
|
||||
@@ -2499,8 +2508,9 @@ static bool InlineGrowableArraySetter(FlowGraph* flow_graph,
|
||||
Definition* array = receiver;
|
||||
Definition* value = call->ArgumentAt(1);
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
|
||||
// This is an internal method, no need to check argument types.
|
||||
@@ -2585,8 +2595,9 @@ static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph,
|
||||
ASSERT(array_cid != kIllegalCid);
|
||||
Definition* array = receiver;
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
|
||||
@@ -2628,8 +2639,9 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
|
||||
ASSERT(array_cid != kIllegalCid);
|
||||
Definition* array = receiver;
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
|
||||
@@ -2794,8 +2806,9 @@ static bool InlineStringBaseCharAt(FlowGraph* flow_graph,
|
||||
Definition* str = receiver;
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
|
||||
*last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
|
||||
@@ -2822,8 +2835,9 @@ static bool InlineStringCodeUnitAt(FlowGraph* flow_graph,
|
||||
Definition* str = receiver;
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
|
||||
*last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
|
||||
@@ -2935,8 +2949,9 @@ static bool InlineFloat32x4Method(FlowGraph* flow_graph,
|
||||
return false;
|
||||
}
|
||||
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
switch (kind) {
|
||||
@@ -3053,8 +3068,9 @@ static bool InlineSimdShuffleMethod(FlowGraph* flow_graph,
|
||||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
Definition* mask_definition = call->ArgumentAt(1);
|
||||
@@ -3081,8 +3097,9 @@ static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph,
|
||||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
Definition* mask_definition = call->ArgumentAt(2);
|
||||
@@ -3110,8 +3127,9 @@ static bool InlineInt32x4Method(FlowGraph* flow_graph,
|
||||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
switch (kind) {
|
||||
@@ -3166,8 +3184,9 @@ static bool InlineFloat64x2Method(FlowGraph* flow_graph,
|
||||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
switch (kind) {
|
||||
@@ -3217,8 +3236,9 @@ static bool InlineSimdConstructor(FlowGraph* flow_graph,
|
||||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
switch (kind) {
|
||||
@@ -3298,8 +3318,9 @@ static bool InlineMathCFunction(FlowGraph* flow_graph,
|
||||
if (!CanUnboxDouble()) {
|
||||
return false;
|
||||
}
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Instruction* cursor = *entry;
|
||||
|
||||
@@ -3660,8 +3681,9 @@ bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
|
||||
return InlineMathCFunction(flow_graph, call, kind, entry, last);
|
||||
|
||||
case MethodRecognizer::kObjectConstructor: {
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
ASSERT(!call->HasUses());
|
||||
*last = NULL; // Empty body.
|
||||
@@ -3676,10 +3698,11 @@ bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
|
||||
if (length >= 0 && length <= Array::kMaxElements) {
|
||||
Value* type = new (Z) Value(call->ArgumentAt(0));
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
call->GetBlock()->try_index(),
|
||||
Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
*last =
|
||||
new (Z) CreateArrayInstr(call->token_pos(), type, num_elements);
|
||||
*last = new (Z) CreateArrayInstr(call->token_pos(), type,
|
||||
num_elements, call->deopt_id());
|
||||
flow_graph->AppendTo(
|
||||
*entry, *last,
|
||||
call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL,
|
||||
@@ -3707,8 +3730,9 @@ bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
|
||||
}
|
||||
|
||||
if (!type.IsNull()) {
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
*last = new (Z) ConstantInstr(type);
|
||||
flow_graph->AppendTo(
|
||||
@@ -3723,8 +3747,9 @@ bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
|
||||
case MethodRecognizer::kOneByteStringSetAt: {
|
||||
// This is an internal method, no need to check argument types nor
|
||||
// range.
|
||||
*entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
*entry = new (Z)
|
||||
TargetEntryInstr(flow_graph->allocate_block_id(),
|
||||
call->GetBlock()->try_index(), Thread::kNoDeoptId);
|
||||
(*entry)->InheritDeoptTarget(Z, call);
|
||||
Definition* str = call->ArgumentAt(0);
|
||||
Definition* index = call->ArgumentAt(1);
|
||||
|
||||
@@ -604,7 +604,9 @@ const Object& Value::BoundConstant() const {
|
||||
GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function,
|
||||
TargetEntryInstr* normal_entry,
|
||||
intptr_t osr_id)
|
||||
: BlockEntryInstr(0, CatchClauseNode::kInvalidTryIndex),
|
||||
: BlockEntryInstr(0,
|
||||
CatchClauseNode::kInvalidTryIndex,
|
||||
Thread::Current()->GetNextDeoptId()),
|
||||
parsed_function_(parsed_function),
|
||||
normal_entry_(normal_entry),
|
||||
catch_entries_(),
|
||||
@@ -1109,7 +1111,8 @@ bool BlockEntryInstr::PruneUnreachable(GraphEntryInstr* graph_entry,
|
||||
// we can simply jump to the beginning of the block.
|
||||
ASSERT(instr->previous() == this);
|
||||
|
||||
GotoInstr* goto_join = new GotoInstr(AsJoinEntry());
|
||||
GotoInstr* goto_join =
|
||||
new GotoInstr(AsJoinEntry(), Thread::Current()->GetNextDeoptId());
|
||||
goto_join->CopyDeoptIdFrom(*parent);
|
||||
graph_entry->normal_entry()->LinkTo(goto_join);
|
||||
return true;
|
||||
@@ -1336,7 +1339,7 @@ BlockEntryInstr* GotoInstr::SuccessorAt(intptr_t index) const {
|
||||
|
||||
|
||||
void Instruction::Goto(JoinEntryInstr* entry) {
|
||||
LinkTo(new GotoInstr(entry));
|
||||
LinkTo(new GotoInstr(entry, Thread::Current()->GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -3222,8 +3225,9 @@ StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos,
|
||||
Token::Kind kind,
|
||||
Value* left,
|
||||
Value* right,
|
||||
bool needs_number_check)
|
||||
: TemplateComparison(token_pos, kind, Thread::Current()->GetNextDeoptId()),
|
||||
bool needs_number_check,
|
||||
intptr_t deopt_id)
|
||||
: TemplateComparison(token_pos, kind, deopt_id),
|
||||
needs_number_check_(needs_number_check) {
|
||||
ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
|
||||
SetInputAt(0, left);
|
||||
@@ -3834,7 +3838,7 @@ ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left,
|
||||
ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left,
|
||||
Value* new_right) {
|
||||
return new StrictCompareInstr(token_pos(), kind(), new_left, new_right,
|
||||
needs_number_check());
|
||||
needs_number_check(), Thread::kNoDeoptId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1262,8 +1262,8 @@ class BlockEntryInstr : public Instruction {
|
||||
DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry)
|
||||
|
||||
protected:
|
||||
BlockEntryInstr(intptr_t block_id, intptr_t try_index)
|
||||
: Instruction(Thread::Current()->GetNextDeoptId()),
|
||||
BlockEntryInstr(intptr_t block_id, intptr_t try_index, intptr_t deopt_id)
|
||||
: Instruction(deopt_id),
|
||||
block_id_(block_id),
|
||||
try_index_(try_index),
|
||||
preorder_number_(-1),
|
||||
@@ -1442,8 +1442,8 @@ class GraphEntryInstr : public BlockEntryInstr {
|
||||
|
||||
class JoinEntryInstr : public BlockEntryInstr {
|
||||
public:
|
||||
JoinEntryInstr(intptr_t block_id, intptr_t try_index)
|
||||
: BlockEntryInstr(block_id, try_index),
|
||||
JoinEntryInstr(intptr_t block_id, intptr_t try_index, intptr_t deopt_id)
|
||||
: BlockEntryInstr(block_id, try_index, deopt_id),
|
||||
predecessors_(2), // Two is the assumed to be the common case.
|
||||
phis_(NULL) {}
|
||||
|
||||
@@ -1512,8 +1512,8 @@ class PhiIterator : public ValueObject {
|
||||
|
||||
class TargetEntryInstr : public BlockEntryInstr {
|
||||
public:
|
||||
TargetEntryInstr(intptr_t block_id, intptr_t try_index)
|
||||
: BlockEntryInstr(block_id, try_index),
|
||||
TargetEntryInstr(intptr_t block_id, intptr_t try_index, intptr_t deopt_id)
|
||||
: BlockEntryInstr(block_id, try_index, deopt_id),
|
||||
predecessor_(NULL),
|
||||
edge_weight_(0.0) {}
|
||||
|
||||
@@ -1553,8 +1553,10 @@ class IndirectEntryInstr : public JoinEntryInstr {
|
||||
public:
|
||||
IndirectEntryInstr(intptr_t block_id,
|
||||
intptr_t indirect_id,
|
||||
intptr_t try_index)
|
||||
: JoinEntryInstr(block_id, try_index), indirect_id_(indirect_id) {}
|
||||
intptr_t try_index,
|
||||
intptr_t deopt_id)
|
||||
: JoinEntryInstr(block_id, try_index, deopt_id),
|
||||
indirect_id_(indirect_id) {}
|
||||
|
||||
DECLARE_INSTRUCTION(IndirectEntry)
|
||||
|
||||
@@ -1581,7 +1583,7 @@ class CatchBlockEntryInstr : public BlockEntryInstr {
|
||||
bool needs_stacktrace,
|
||||
intptr_t deopt_id,
|
||||
bool should_restore_closure_context = false)
|
||||
: BlockEntryInstr(block_id, try_index),
|
||||
: BlockEntryInstr(block_id, try_index, deopt_id),
|
||||
graph_entry_(graph_entry),
|
||||
predecessor_(NULL),
|
||||
catch_handler_types_(Array::ZoneHandle(handler_types.raw())),
|
||||
@@ -1591,9 +1593,7 @@ class CatchBlockEntryInstr : public BlockEntryInstr {
|
||||
needs_stacktrace_(needs_stacktrace),
|
||||
should_restore_closure_context_(should_restore_closure_context),
|
||||
handler_token_pos_(handler_token_pos),
|
||||
is_generated_(is_generated) {
|
||||
deopt_id_ = deopt_id;
|
||||
}
|
||||
is_generated_(is_generated) {}
|
||||
|
||||
DECLARE_INSTRUCTION(CatchBlockEntry)
|
||||
|
||||
@@ -2108,9 +2108,8 @@ inline Definition* Instruction::ArgumentAt(intptr_t index) const {
|
||||
|
||||
class ReturnInstr : public TemplateInstruction<1, NoThrow> {
|
||||
public:
|
||||
ReturnInstr(TokenPosition token_pos, Value* value)
|
||||
: TemplateInstruction(Thread::Current()->GetNextDeoptId()),
|
||||
token_pos_(token_pos) {
|
||||
ReturnInstr(TokenPosition token_pos, Value* value, intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id), token_pos_(token_pos) {
|
||||
SetInputAt(0, value);
|
||||
}
|
||||
|
||||
@@ -2138,9 +2137,8 @@ class ReturnInstr : public TemplateInstruction<1, NoThrow> {
|
||||
|
||||
class ThrowInstr : public TemplateInstruction<0, Throws> {
|
||||
public:
|
||||
explicit ThrowInstr(TokenPosition token_pos)
|
||||
: TemplateInstruction(Thread::Current()->GetNextDeoptId()),
|
||||
token_pos_(token_pos) {}
|
||||
explicit ThrowInstr(TokenPosition token_pos, intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id), token_pos_(token_pos) {}
|
||||
|
||||
DECLARE_INSTRUCTION(Throw)
|
||||
|
||||
@@ -2163,8 +2161,10 @@ class ReThrowInstr : public TemplateInstruction<0, Throws> {
|
||||
public:
|
||||
// 'catch_try_index' can be CatchClauseNode::kInvalidTryIndex if the
|
||||
// rethrow has been artificially generated by the parser.
|
||||
ReThrowInstr(TokenPosition token_pos, intptr_t catch_try_index)
|
||||
: TemplateInstruction(Thread::Current()->GetNextDeoptId()),
|
||||
ReThrowInstr(TokenPosition token_pos,
|
||||
intptr_t catch_try_index,
|
||||
intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id),
|
||||
token_pos_(token_pos),
|
||||
catch_try_index_(catch_try_index) {}
|
||||
|
||||
@@ -2214,8 +2214,8 @@ class StopInstr : public TemplateInstruction<0, NoThrow> {
|
||||
|
||||
class GotoInstr : public TemplateInstruction<0, NoThrow> {
|
||||
public:
|
||||
explicit GotoInstr(JoinEntryInstr* entry)
|
||||
: TemplateInstruction(Thread::Current()->GetNextDeoptId()),
|
||||
explicit GotoInstr(JoinEntryInstr* entry, intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id),
|
||||
block_(NULL),
|
||||
successor_(entry),
|
||||
edge_weight_(0.0),
|
||||
@@ -2428,10 +2428,8 @@ class TemplateComparison
|
||||
|
||||
class BranchInstr : public Instruction {
|
||||
public:
|
||||
explicit BranchInstr(ComparisonInstr* comparison)
|
||||
: Instruction(Thread::Current()->GetNextDeoptId()),
|
||||
comparison_(comparison),
|
||||
constant_target_(NULL) {
|
||||
explicit BranchInstr(ComparisonInstr* comparison, intptr_t deopt_id)
|
||||
: Instruction(deopt_id), comparison_(comparison), constant_target_(NULL) {
|
||||
ASSERT(comparison->env() == NULL);
|
||||
for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
|
||||
comparison->InputAt(i)->set_instruction(this);
|
||||
@@ -2710,9 +2708,8 @@ class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
|
||||
|
||||
class AssertBooleanInstr : public TemplateDefinition<1, Throws, Pure> {
|
||||
public:
|
||||
AssertBooleanInstr(TokenPosition token_pos, Value* value)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
token_pos_(token_pos) {
|
||||
AssertBooleanInstr(TokenPosition token_pos, Value* value, intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id), token_pos_(token_pos) {
|
||||
SetInputAt(0, value);
|
||||
}
|
||||
|
||||
@@ -2741,8 +2738,8 @@ class AssertBooleanInstr : public TemplateDefinition<1, Throws, Pure> {
|
||||
// a computation, not a value, because it's mutable.
|
||||
class CurrentContextInstr : public TemplateDefinition<0, NoThrow> {
|
||||
public:
|
||||
CurrentContextInstr()
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()) {}
|
||||
explicit CurrentContextInstr(intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id) {}
|
||||
|
||||
DECLARE_INSTRUCTION(CurrentContext)
|
||||
virtual CompileType ComputeType() const;
|
||||
@@ -2825,8 +2822,9 @@ class ClosureCallInstr : public TemplateDartCall<1> {
|
||||
public:
|
||||
ClosureCallInstr(Value* function,
|
||||
ClosureCallNode* node,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments)
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDartCall(deopt_id,
|
||||
node->arguments()->type_args_len(),
|
||||
node->arguments()->names(),
|
||||
arguments,
|
||||
@@ -2839,8 +2837,9 @@ class ClosureCallInstr : public TemplateDartCall<1> {
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
TokenPosition token_pos)
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
TokenPosition token_pos,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDartCall(deopt_id,
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
@@ -2874,8 +2873,9 @@ class InstanceCallInstr : public TemplateDartCall<0> {
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
intptr_t checked_argument_count,
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array)
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDartCall(deopt_id,
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
@@ -3033,7 +3033,8 @@ class StrictCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
|
||||
Token::Kind kind,
|
||||
Value* left,
|
||||
Value* right,
|
||||
bool needs_number_check);
|
||||
bool needs_number_check,
|
||||
intptr_t deopt_id);
|
||||
|
||||
DECLARE_INSTRUCTION(StrictCompare)
|
||||
|
||||
@@ -3245,8 +3246,11 @@ class RelationalOpInstr : public TemplateComparison<2, NoThrow, Pure> {
|
||||
// materialization of true and false constants.
|
||||
class IfThenElseInstr : public Definition {
|
||||
public:
|
||||
IfThenElseInstr(ComparisonInstr* comparison, Value* if_true, Value* if_false)
|
||||
: Definition(Thread::Current()->GetNextDeoptId()),
|
||||
IfThenElseInstr(ComparisonInstr* comparison,
|
||||
Value* if_true,
|
||||
Value* if_false,
|
||||
intptr_t deopt_id)
|
||||
: Definition(deopt_id),
|
||||
comparison_(comparison),
|
||||
if_true_(Smi::Cast(if_true->BoundConstant()).Value()),
|
||||
if_false_(Smi::Cast(if_false->BoundConstant()).Value()) {
|
||||
@@ -3328,8 +3332,9 @@ class StaticCallInstr : public TemplateDartCall<0> {
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array)
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDartCall(deopt_id,
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
@@ -4049,8 +4054,10 @@ class StringToCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
||||
|
||||
class StringInterpolateInstr : public TemplateDefinition<1, Throws> {
|
||||
public:
|
||||
StringInterpolateInstr(Value* value, TokenPosition token_pos)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
StringInterpolateInstr(Value* value,
|
||||
TokenPosition token_pos,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id),
|
||||
token_pos_(token_pos),
|
||||
function_(Function::ZoneHandle()) {
|
||||
SetInputAt(0, value);
|
||||
@@ -4385,8 +4392,9 @@ class CreateArrayInstr : public TemplateDefinition<2, Throws> {
|
||||
public:
|
||||
CreateArrayInstr(TokenPosition token_pos,
|
||||
Value* element_type,
|
||||
Value* num_elements)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
Value* num_elements,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id),
|
||||
token_pos_(token_pos),
|
||||
identity_(AliasIdentity::Unknown()) {
|
||||
SetInputAt(kElementTypePos, element_type);
|
||||
@@ -4594,10 +4602,9 @@ class InstantiateTypeInstr : public TemplateDefinition<2, Throws> {
|
||||
InstantiateTypeInstr(TokenPosition token_pos,
|
||||
const AbstractType& type,
|
||||
Value* instantiator_type_arguments,
|
||||
Value* function_type_arguments)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
token_pos_(token_pos),
|
||||
type_(type) {
|
||||
Value* function_type_arguments,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id), token_pos_(token_pos), type_(type) {
|
||||
ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
|
||||
SetInputAt(0, instantiator_type_arguments);
|
||||
SetInputAt(1, function_type_arguments);
|
||||
@@ -4630,8 +4637,9 @@ class InstantiateTypeArgumentsInstr : public TemplateDefinition<2, Throws> {
|
||||
const TypeArguments& type_arguments,
|
||||
const Class& instantiator_class,
|
||||
Value* instantiator_type_arguments,
|
||||
Value* function_type_arguments)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
Value* function_type_arguments,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id),
|
||||
token_pos_(token_pos),
|
||||
type_arguments_(type_arguments),
|
||||
instantiator_class_(instantiator_class) {
|
||||
@@ -4692,9 +4700,8 @@ class AllocateContextInstr : public TemplateDefinition<0, NoThrow> {
|
||||
|
||||
class InitStaticFieldInstr : public TemplateInstruction<1, Throws> {
|
||||
public:
|
||||
InitStaticFieldInstr(Value* input, const Field& field)
|
||||
: TemplateInstruction(Thread::Current()->GetNextDeoptId()),
|
||||
field_(field) {
|
||||
InitStaticFieldInstr(Value* input, const Field& field, intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id), field_(field) {
|
||||
SetInputAt(0, input);
|
||||
CheckField(field);
|
||||
}
|
||||
@@ -4717,9 +4724,10 @@ class InitStaticFieldInstr : public TemplateInstruction<1, Throws> {
|
||||
|
||||
class CloneContextInstr : public TemplateDefinition<1, NoThrow> {
|
||||
public:
|
||||
CloneContextInstr(TokenPosition token_pos, Value* context_value)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
token_pos_(token_pos) {
|
||||
CloneContextInstr(TokenPosition token_pos,
|
||||
Value* context_value,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id), token_pos_(token_pos) {
|
||||
SetInputAt(0, context_value);
|
||||
}
|
||||
|
||||
@@ -7254,8 +7262,10 @@ class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
||||
|
||||
class CheckStackOverflowInstr : public TemplateInstruction<0, NoThrow> {
|
||||
public:
|
||||
CheckStackOverflowInstr(TokenPosition token_pos, intptr_t loop_depth)
|
||||
: TemplateInstruction(Thread::Current()->GetNextDeoptId()),
|
||||
CheckStackOverflowInstr(TokenPosition token_pos,
|
||||
intptr_t loop_depth,
|
||||
intptr_t deopt_id)
|
||||
: TemplateInstruction(deopt_id),
|
||||
token_pos_(token_pos),
|
||||
loop_depth_(loop_depth) {}
|
||||
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
namespace dart {
|
||||
|
||||
TEST_CASE(InstructionTests) {
|
||||
TargetEntryInstr* target_instr =
|
||||
new TargetEntryInstr(1, CatchClauseNode::kInvalidTryIndex);
|
||||
TargetEntryInstr* target_instr = new TargetEntryInstr(
|
||||
1, CatchClauseNode::kInvalidTryIndex, Thread::kNoDeoptId);
|
||||
EXPECT(target_instr->IsBlockEntry());
|
||||
EXPECT(!target_instr->IsDefinition());
|
||||
CurrentContextInstr* context = new CurrentContextInstr();
|
||||
CurrentContextInstr* context = new CurrentContextInstr(Thread::kNoDeoptId);
|
||||
EXPECT(context->IsDefinition());
|
||||
EXPECT(!context->IsBlockEntry());
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(OptimizationTests) {
|
||||
JoinEntryInstr* join =
|
||||
new JoinEntryInstr(1, CatchClauseNode::kInvalidTryIndex);
|
||||
JoinEntryInstr* join = new JoinEntryInstr(
|
||||
1, CatchClauseNode::kInvalidTryIndex, Thread::kNoDeoptId);
|
||||
|
||||
Definition* def1 = new PhiInstr(join, 0);
|
||||
Definition* def2 = new PhiInstr(join, 0);
|
||||
|
||||
@@ -170,7 +170,8 @@ bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
|
||||
|
||||
intptr_t block_id = builder.AllocateBlockId();
|
||||
TargetEntryInstr* normal_entry =
|
||||
new TargetEntryInstr(block_id, CatchClauseNode::kInvalidTryIndex);
|
||||
new TargetEntryInstr(block_id, CatchClauseNode::kInvalidTryIndex,
|
||||
Thread::Current()->GetNextDeoptId());
|
||||
GraphEntryInstr* graph_entry = new GraphEntryInstr(
|
||||
parsed_function, normal_entry, Compiler::kNoOSRDeoptId);
|
||||
FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id);
|
||||
@@ -318,7 +319,8 @@ class BlockBuilder : public ValueObject {
|
||||
}
|
||||
|
||||
void AddIntrinsicReturn(Value* value) {
|
||||
ReturnInstr* instr = new ReturnInstr(TokenPos(), value);
|
||||
ReturnInstr* instr =
|
||||
new ReturnInstr(TokenPos(), value, Thread::Current()->GetNextDeoptId());
|
||||
AddInstruction(instr);
|
||||
entry_->set_last_instruction(instr);
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ bool JitOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
||||
StrictCompareInstr* comp = new (Z)
|
||||
StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
|
||||
new (Z) Value(left), new (Z) Value(right),
|
||||
false); // No number check.
|
||||
/* number_check = */ false, Thread::kNoDeoptId);
|
||||
ReplaceCall(call, comp);
|
||||
return true;
|
||||
}
|
||||
@@ -1356,10 +1356,9 @@ void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
||||
ConstantInstr* cid =
|
||||
flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid)));
|
||||
|
||||
StrictCompareInstr* check_cid =
|
||||
new (Z) StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
|
||||
new (Z) Value(left_cid), new (Z) Value(cid),
|
||||
false); // No number check.
|
||||
StrictCompareInstr* check_cid = new (Z) StrictCompareInstr(
|
||||
call->token_pos(), Token::kEQ_STRICT, new (Z) Value(left_cid),
|
||||
new (Z) Value(cid), /* number_check = */ false, Thread::kNoDeoptId);
|
||||
ReplaceCall(call, check_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3554,7 +3554,7 @@ Fragment StreamingFlowGraphBuilder::BuildWhileStatement() {
|
||||
Fragment loop(join);
|
||||
loop += CheckStackOverflow();
|
||||
loop += condition;
|
||||
entry = new (Z) GotoInstr(join);
|
||||
entry = new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId());
|
||||
} else {
|
||||
entry = condition.entry;
|
||||
}
|
||||
@@ -3588,7 +3588,8 @@ Fragment StreamingFlowGraphBuilder::BuildDoStatement() {
|
||||
repeat += Goto(join);
|
||||
|
||||
loop_depth_dec();
|
||||
return Fragment(new (Z) GotoInstr(join), loop_exit);
|
||||
return Fragment(new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId()),
|
||||
loop_exit);
|
||||
}
|
||||
|
||||
Fragment StreamingFlowGraphBuilder::BuildForStatement() {
|
||||
|
||||
+51
-42
@@ -2017,6 +2017,7 @@ FlowGraphBuilder::FlowGraphBuilder(
|
||||
intptr_t osr_id,
|
||||
intptr_t first_block_id)
|
||||
: translation_helper_(Thread::Current()),
|
||||
thread_(translation_helper_.thread()),
|
||||
zone_(translation_helper_.zone()),
|
||||
node_(node),
|
||||
parsed_function_(parsed_function),
|
||||
@@ -2248,9 +2249,9 @@ Fragment FlowGraphBuilder::LoadFunctionTypeArguments() {
|
||||
Fragment FlowGraphBuilder::InstantiateType(const AbstractType& type) {
|
||||
Value* function_type_args = Pop();
|
||||
Value* instantiator_type_args = Pop();
|
||||
InstantiateTypeInstr* instr =
|
||||
new (Z) InstantiateTypeInstr(TokenPosition::kNoSource, type,
|
||||
instantiator_type_args, function_type_args);
|
||||
InstantiateTypeInstr* instr = new (Z) InstantiateTypeInstr(
|
||||
TokenPosition::kNoSource, type, instantiator_type_args,
|
||||
function_type_args, GetNextDeoptId());
|
||||
Push(instr);
|
||||
return Fragment(instr);
|
||||
}
|
||||
@@ -2262,7 +2263,7 @@ Fragment FlowGraphBuilder::InstantiateTypeArguments(
|
||||
Value* instantiator_type_args = Pop();
|
||||
InstantiateTypeArgumentsInstr* instr = new (Z) InstantiateTypeArgumentsInstr(
|
||||
TokenPosition::kNoSource, type_arguments, *active_class_.klass,
|
||||
instantiator_type_args, function_type_args);
|
||||
instantiator_type_args, function_type_args, GetNextDeoptId());
|
||||
Push(instr);
|
||||
return Fragment(instr);
|
||||
}
|
||||
@@ -2352,8 +2353,9 @@ Fragment FlowGraphBuilder::StrictCompare(Token::Kind kind,
|
||||
bool number_check /* = false */) {
|
||||
Value* right = Pop();
|
||||
Value* left = Pop();
|
||||
StrictCompareInstr* compare = new (Z) StrictCompareInstr(
|
||||
TokenPosition::kNoSource, kind, left, right, number_check);
|
||||
StrictCompareInstr* compare =
|
||||
new (Z) StrictCompareInstr(TokenPosition::kNoSource, kind, left, right,
|
||||
number_check, GetNextDeoptId());
|
||||
Push(compare);
|
||||
return Fragment(compare);
|
||||
}
|
||||
@@ -2381,8 +2383,8 @@ Fragment FlowGraphBuilder::BranchIfEqual(TargetEntryInstr** then_entry,
|
||||
Value* left_value = Pop();
|
||||
StrictCompareInstr* compare = new (Z) StrictCompareInstr(
|
||||
TokenPosition::kNoSource, negate ? Token::kNE_STRICT : Token::kEQ_STRICT,
|
||||
left_value, right_value, false);
|
||||
BranchInstr* branch = new (Z) BranchInstr(compare);
|
||||
left_value, right_value, false, GetNextDeoptId());
|
||||
BranchInstr* branch = new (Z) BranchInstr(compare, GetNextDeoptId());
|
||||
*then_entry = *branch->true_successor_address() = BuildTargetEntry();
|
||||
*otherwise_entry = *branch->false_successor_address() = BuildTargetEntry();
|
||||
return Fragment(branch).closed();
|
||||
@@ -2394,9 +2396,10 @@ Fragment FlowGraphBuilder::BranchIfStrictEqual(
|
||||
TargetEntryInstr** otherwise_entry) {
|
||||
Value* rhs = Pop();
|
||||
Value* lhs = Pop();
|
||||
StrictCompareInstr* compare = new (Z) StrictCompareInstr(
|
||||
TokenPosition::kNoSource, Token::kEQ_STRICT, lhs, rhs, false);
|
||||
BranchInstr* branch = new (Z) BranchInstr(compare);
|
||||
StrictCompareInstr* compare =
|
||||
new (Z) StrictCompareInstr(TokenPosition::kNoSource, Token::kEQ_STRICT,
|
||||
lhs, rhs, false, GetNextDeoptId());
|
||||
BranchInstr* branch = new (Z) BranchInstr(compare, GetNextDeoptId());
|
||||
*then_entry = *branch->true_successor_address() = BuildTargetEntry();
|
||||
*otherwise_entry = *branch->false_successor_address() = BuildTargetEntry();
|
||||
return Fragment(branch).closed();
|
||||
@@ -2446,8 +2449,8 @@ Fragment FlowGraphBuilder::TryCatch(int try_handler_index) {
|
||||
// => We therefore create a block for the body (fresh try index) and another
|
||||
// join block (with current try index).
|
||||
Fragment body;
|
||||
JoinEntryInstr* entry =
|
||||
new (Z) JoinEntryInstr(AllocateBlockId(), try_handler_index);
|
||||
JoinEntryInstr* entry = new (Z)
|
||||
JoinEntryInstr(AllocateBlockId(), try_handler_index, GetNextDeoptId());
|
||||
body += LoadLocal(parsed_function_->current_context_var());
|
||||
body += StoreLocal(TokenPosition::kNoSource, CurrentCatchContext());
|
||||
body += Drop();
|
||||
@@ -2468,8 +2471,8 @@ Fragment FlowGraphBuilder::CheckStackOverflowInPrologue() {
|
||||
|
||||
|
||||
Fragment FlowGraphBuilder::CheckStackOverflow() {
|
||||
return Fragment(
|
||||
new (Z) CheckStackOverflowInstr(TokenPosition::kNoSource, loop_depth_));
|
||||
return Fragment(new (Z) CheckStackOverflowInstr(
|
||||
TokenPosition::kNoSource, loop_depth_, GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -2478,8 +2481,8 @@ Fragment FlowGraphBuilder::CloneContext() {
|
||||
|
||||
Fragment instructions = LoadLocal(context_variable);
|
||||
|
||||
CloneContextInstr* clone_instruction =
|
||||
new (Z) CloneContextInstr(TokenPosition::kNoSource, Pop());
|
||||
CloneContextInstr* clone_instruction = new (Z)
|
||||
CloneContextInstr(TokenPosition::kNoSource, Pop(), GetNextDeoptId());
|
||||
instructions <<= clone_instruction;
|
||||
Push(clone_instruction);
|
||||
|
||||
@@ -2499,16 +2502,17 @@ Fragment FlowGraphBuilder::Constant(const Object& value) {
|
||||
|
||||
Fragment FlowGraphBuilder::CreateArray() {
|
||||
Value* element_count = Pop();
|
||||
CreateArrayInstr* array = new (Z) CreateArrayInstr(TokenPosition::kNoSource,
|
||||
Pop(), // Element type.
|
||||
element_count);
|
||||
CreateArrayInstr* array =
|
||||
new (Z) CreateArrayInstr(TokenPosition::kNoSource,
|
||||
Pop(), // Element type.
|
||||
element_count, GetNextDeoptId());
|
||||
Push(array);
|
||||
return Fragment(array);
|
||||
}
|
||||
|
||||
|
||||
Fragment FlowGraphBuilder::Goto(JoinEntryInstr* destination) {
|
||||
return Fragment(new (Z) GotoInstr(destination)).closed();
|
||||
return Fragment(new (Z) GotoInstr(destination, GetNextDeoptId())).closed();
|
||||
}
|
||||
|
||||
|
||||
@@ -2536,9 +2540,9 @@ Fragment FlowGraphBuilder::InstanceCall(TokenPosition position,
|
||||
intptr_t num_args_checked) {
|
||||
ArgumentArray arguments = GetArguments(argument_count);
|
||||
const intptr_t kTypeArgsLen = 0; // Generic instance calls not yet supported.
|
||||
InstanceCallInstr* call = new (Z)
|
||||
InstanceCallInstr(position, name, kind, arguments, kTypeArgsLen,
|
||||
argument_names, num_args_checked, ic_data_array_);
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
position, name, kind, arguments, kTypeArgsLen, argument_names,
|
||||
num_args_checked, ic_data_array_, GetNextDeoptId());
|
||||
Push(call);
|
||||
return Fragment(call);
|
||||
}
|
||||
@@ -2549,9 +2553,9 @@ Fragment FlowGraphBuilder::ClosureCall(int argument_count,
|
||||
Value* function = Pop();
|
||||
ArgumentArray arguments = GetArguments(argument_count);
|
||||
const intptr_t kTypeArgsLen = 0; // Generic closures not yet supported.
|
||||
ClosureCallInstr* call =
|
||||
new (Z) ClosureCallInstr(function, arguments, kTypeArgsLen,
|
||||
argument_names, TokenPosition::kNoSource);
|
||||
ClosureCallInstr* call = new (Z)
|
||||
ClosureCallInstr(function, arguments, kTypeArgsLen, argument_names,
|
||||
TokenPosition::kNoSource, GetNextDeoptId());
|
||||
Push(call);
|
||||
return Fragment(call);
|
||||
}
|
||||
@@ -2560,7 +2564,8 @@ Fragment FlowGraphBuilder::ClosureCall(int argument_count,
|
||||
Fragment FlowGraphBuilder::ThrowException(TokenPosition position) {
|
||||
Fragment instructions;
|
||||
instructions += Drop();
|
||||
instructions += Fragment(new (Z) ThrowInstr(position)).closed();
|
||||
instructions +=
|
||||
Fragment(new (Z) ThrowInstr(position, GetNextDeoptId())).closed();
|
||||
// Use it's side effect of leaving a constant on the stack (does not change
|
||||
// the graph).
|
||||
NullConstant();
|
||||
@@ -2576,8 +2581,9 @@ Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
|
||||
Fragment instructions;
|
||||
instructions += Drop();
|
||||
instructions += Drop();
|
||||
instructions +=
|
||||
Fragment(new (Z) ReThrowInstr(position, catch_try_index)).closed();
|
||||
instructions += Fragment(new (Z) ReThrowInstr(position, catch_try_index,
|
||||
GetNextDeoptId()))
|
||||
.closed();
|
||||
// Use it's side effect of leaving a constant on the stack (does not change
|
||||
// the graph).
|
||||
NullConstant();
|
||||
@@ -2657,8 +2663,8 @@ Fragment FlowGraphBuilder::LoadLocal(LocalVariable* variable) {
|
||||
|
||||
|
||||
Fragment FlowGraphBuilder::InitStaticField(const dart::Field& field) {
|
||||
InitStaticFieldInstr* init =
|
||||
new (Z) InitStaticFieldInstr(Pop(), MayCloneField(Z, field));
|
||||
InitStaticFieldInstr* init = new (Z)
|
||||
InitStaticFieldInstr(Pop(), MayCloneField(Z, field), GetNextDeoptId());
|
||||
return Fragment(init);
|
||||
}
|
||||
|
||||
@@ -2721,7 +2727,8 @@ Fragment FlowGraphBuilder::Return(TokenPosition position) {
|
||||
instructions += Drop();
|
||||
}
|
||||
|
||||
ReturnInstr* return_instr = new (Z) ReturnInstr(position, value);
|
||||
ReturnInstr* return_instr =
|
||||
new (Z) ReturnInstr(position, value, GetNextDeoptId());
|
||||
if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr);
|
||||
|
||||
instructions <<= return_instr;
|
||||
@@ -2767,7 +2774,7 @@ Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
|
||||
const intptr_t kTypeArgsLen = 0; // Generic static calls not yet supported.
|
||||
StaticCallInstr* call =
|
||||
new (Z) StaticCallInstr(position, target, kTypeArgsLen, argument_names,
|
||||
arguments, ic_data_array_);
|
||||
arguments, ic_data_array_, GetNextDeoptId());
|
||||
const intptr_t list_cid =
|
||||
GetResultCidOfListFactory(Z, target, argument_count);
|
||||
if (list_cid != kDynamicCid) {
|
||||
@@ -2881,7 +2888,7 @@ Fragment FlowGraphBuilder::StoreStaticField(TokenPosition position,
|
||||
Fragment FlowGraphBuilder::StringInterpolate(TokenPosition position) {
|
||||
Value* array = Pop();
|
||||
StringInterpolateInstr* interpolate =
|
||||
new (Z) StringInterpolateInstr(array, position);
|
||||
new (Z) StringInterpolateInstr(array, position, GetNextDeoptId());
|
||||
Push(interpolate);
|
||||
return Fragment(interpolate);
|
||||
}
|
||||
@@ -3931,8 +3938,8 @@ Fragment FlowGraphBuilder::CheckAssignableInCheckedMode(
|
||||
|
||||
Fragment FlowGraphBuilder::AssertBool() {
|
||||
Value* value = Pop();
|
||||
AssertBooleanInstr* instr =
|
||||
new (Z) AssertBooleanInstr(TokenPosition::kNoSource, value);
|
||||
AssertBooleanInstr* instr = new (Z)
|
||||
AssertBooleanInstr(TokenPosition::kNoSource, value, GetNextDeoptId());
|
||||
Push(instr);
|
||||
return Fragment(instr);
|
||||
}
|
||||
@@ -4271,17 +4278,19 @@ void FlowGraphBuilder::SetupDefaultParameterValues(FunctionNode* function) {
|
||||
|
||||
|
||||
TargetEntryInstr* FlowGraphBuilder::BuildTargetEntry() {
|
||||
return new (Z) TargetEntryInstr(AllocateBlockId(), CurrentTryIndex());
|
||||
return new (Z)
|
||||
TargetEntryInstr(AllocateBlockId(), CurrentTryIndex(), GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
JoinEntryInstr* FlowGraphBuilder::BuildJoinEntry(intptr_t try_index) {
|
||||
return new (Z) JoinEntryInstr(AllocateBlockId(), try_index);
|
||||
return new (Z) JoinEntryInstr(AllocateBlockId(), try_index, GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
JoinEntryInstr* FlowGraphBuilder::BuildJoinEntry() {
|
||||
return new (Z) JoinEntryInstr(AllocateBlockId(), CurrentTryIndex());
|
||||
return new (Z)
|
||||
JoinEntryInstr(AllocateBlockId(), CurrentTryIndex(), GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
@@ -5869,7 +5878,7 @@ void FlowGraphBuilder::VisitWhileStatement(WhileStatement* node) {
|
||||
Fragment loop(join);
|
||||
loop += CheckStackOverflow();
|
||||
loop += condition;
|
||||
entry = new (Z) GotoInstr(join);
|
||||
entry = new (Z) GotoInstr(join, GetNextDeoptId());
|
||||
} else {
|
||||
entry = condition.entry;
|
||||
}
|
||||
@@ -5905,7 +5914,7 @@ void FlowGraphBuilder::VisitDoStatement(DoStatement* node) {
|
||||
Fragment repeat(loop_repeat);
|
||||
repeat += Goto(join);
|
||||
|
||||
fragment_ = Fragment(new (Z) GotoInstr(join), loop_exit);
|
||||
fragment_ = Fragment(new (Z) GotoInstr(join, GetNextDeoptId()), loop_exit);
|
||||
--loop_depth_;
|
||||
}
|
||||
|
||||
|
||||
@@ -1042,6 +1042,7 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor {
|
||||
void InlineBailout(const char* reason);
|
||||
|
||||
TranslationHelper translation_helper_;
|
||||
Thread* thread_;
|
||||
Zone* zone_;
|
||||
|
||||
// The node we are currently compiling (e.g. FunctionNode, Constructor,
|
||||
@@ -1056,6 +1057,11 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor {
|
||||
intptr_t next_block_id_;
|
||||
intptr_t AllocateBlockId() { return next_block_id_++; }
|
||||
|
||||
intptr_t GetNextDeoptId() {
|
||||
// TODO(rmacnak): Record current scope / context level.
|
||||
return thread_->GetNextDeoptId();
|
||||
}
|
||||
|
||||
intptr_t next_function_id_;
|
||||
intptr_t AllocateFunctionId() { return next_function_id_++; }
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ BlockLabel::BlockLabel()
|
||||
: block_(NULL), is_bound_(false), is_linked_(false), pos_(-1) {
|
||||
if (!FLAG_interpret_irregexp) {
|
||||
// Only needed by the compiled IR backend.
|
||||
block_ = new JoinEntryInstr(-1, -1);
|
||||
block_ = new JoinEntryInstr(-1, -1, Thread::Current()->GetNextDeoptId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array,
|
||||
Zone* zone)
|
||||
: RegExpMacroAssembler(zone),
|
||||
thread_(Thread::Current()),
|
||||
specialization_cid_(specialization_cid),
|
||||
parsed_function_(parsed_function),
|
||||
ic_data_array_(ic_data_array),
|
||||
@@ -122,14 +123,17 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
|
||||
// Create and generate all preset blocks.
|
||||
entry_block_ = new (zone) GraphEntryInstr(
|
||||
*parsed_function_,
|
||||
new (zone) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex),
|
||||
new (zone) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex,
|
||||
GetNextDeoptId()),
|
||||
Compiler::kNoOSRDeoptId);
|
||||
start_block_ = new (zone) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
||||
success_block_ =
|
||||
new (zone) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
||||
backtrack_block_ =
|
||||
new (zone) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
||||
exit_block_ = new (zone) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
||||
start_block_ = new (zone)
|
||||
JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
|
||||
success_block_ = new (zone)
|
||||
JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
|
||||
backtrack_block_ = new (zone)
|
||||
JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
|
||||
exit_block_ = new (zone)
|
||||
JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
|
||||
|
||||
GenerateEntryBlock();
|
||||
GenerateSuccessBlock();
|
||||
@@ -252,8 +256,8 @@ void IRRegExpMacroAssembler::GenerateSuccessBlock() {
|
||||
Value* type = Bind(new (Z) ConstantInstr(
|
||||
TypeArguments::ZoneHandle(Z, TypeArguments::null())));
|
||||
Value* length = Bind(Uint64Constant(saved_registers_count_));
|
||||
Value* array =
|
||||
Bind(new (Z) CreateArrayInstr(TokenPosition::kNoSource, type, length));
|
||||
Value* array = Bind(new (Z) CreateArrayInstr(TokenPosition::kNoSource, type,
|
||||
length, GetNextDeoptId()));
|
||||
StoreLocal(result_, array);
|
||||
|
||||
// Store captured offsets in the `matches` parameter.
|
||||
@@ -276,8 +280,8 @@ void IRRegExpMacroAssembler::GenerateSuccessBlock() {
|
||||
PRINT(PushLocal(result_));
|
||||
|
||||
// Return true on success.
|
||||
AppendInstruction(
|
||||
new (Z) ReturnInstr(TokenPosition::kNoSource, Bind(LoadLocal(result_))));
|
||||
AppendInstruction(new (Z) ReturnInstr(
|
||||
TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -286,8 +290,8 @@ void IRRegExpMacroAssembler::GenerateExitBlock() {
|
||||
TAG();
|
||||
|
||||
// Return false on failure.
|
||||
AppendInstruction(
|
||||
new (Z) ReturnInstr(TokenPosition::kNoSource, Bind(LoadLocal(result_))));
|
||||
AppendInstruction(new (Z) ReturnInstr(
|
||||
TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -489,8 +493,9 @@ ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
|
||||
InstanceCallDescriptor::FromToken(intermediate_operator), lhs, rhs));
|
||||
Value* rhs_value = Bind(BoolConstant(true));
|
||||
|
||||
return new (Z) StrictCompareInstr(TokenPosition::kNoSource, strict_comparison,
|
||||
lhs_value, rhs_value, true);
|
||||
return new (Z)
|
||||
StrictCompareInstr(TokenPosition::kNoSource, strict_comparison, lhs_value,
|
||||
rhs_value, true, GetNextDeoptId());
|
||||
}
|
||||
|
||||
ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
|
||||
@@ -538,9 +543,9 @@ StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
|
||||
const Function& function,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
return new (Z)
|
||||
StaticCallInstr(TokenPosition::kNoSource, function, kTypeArgsLen,
|
||||
Object::null_array(), arguments, ic_data_array_);
|
||||
return new (Z) StaticCallInstr(TokenPosition::kNoSource, function,
|
||||
kTypeArgsLen, Object::null_array(), arguments,
|
||||
ic_data_array_, GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
@@ -587,10 +592,10 @@ InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
|
||||
const InstanceCallDescriptor& desc,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
return new (Z)
|
||||
InstanceCallInstr(TokenPosition::kNoSource, desc.name, desc.token_kind,
|
||||
arguments, kTypeArgsLen, Object::null_array(),
|
||||
desc.checked_argument_count, ic_data_array_);
|
||||
return new (Z) InstanceCallInstr(
|
||||
TokenPosition::kNoSource, desc.name, desc.token_kind, arguments,
|
||||
kTypeArgsLen, Object::null_array(), desc.checked_argument_count,
|
||||
ic_data_array_, GetNextDeoptId());
|
||||
}
|
||||
|
||||
|
||||
@@ -1571,8 +1576,8 @@ void IRRegExpMacroAssembler::CheckStackLimit() {
|
||||
PushArgumentInstr* capacity_push = PushArgument(Bind(Sub(
|
||||
length_push, PushArgument(Bind(Uint64Constant(stack_limit_slack()))))));
|
||||
PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_);
|
||||
BranchInstr* branch =
|
||||
new (Z) BranchInstr(Comparison(kGT, capacity_push, stack_pointer_push));
|
||||
BranchInstr* branch = new (Z) BranchInstr(
|
||||
Comparison(kGT, capacity_push, stack_pointer_push), GetNextDeoptId());
|
||||
CloseBlockWith(branch);
|
||||
|
||||
BlockLabel grow_stack;
|
||||
@@ -1728,7 +1733,7 @@ void IRRegExpMacroAssembler::BranchOrBacktrack(ComparisonInstr* comparison,
|
||||
// If the condition is not true, fall through to a new block.
|
||||
BlockLabel fallthrough;
|
||||
|
||||
BranchInstr* branch = new (Z) BranchInstr(comparison);
|
||||
BranchInstr* branch = new (Z) BranchInstr(comparison, GetNextDeoptId());
|
||||
*branch->true_successor_address() = TargetWithJoinGoto(true_successor_block);
|
||||
*branch->false_successor_address() = TargetWithJoinGoto(fallthrough.block());
|
||||
|
||||
@@ -1739,11 +1744,11 @@ void IRRegExpMacroAssembler::BranchOrBacktrack(ComparisonInstr* comparison,
|
||||
|
||||
TargetEntryInstr* IRRegExpMacroAssembler::TargetWithJoinGoto(
|
||||
JoinEntryInstr* dst) {
|
||||
TargetEntryInstr* target =
|
||||
new (Z) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex);
|
||||
TargetEntryInstr* target = new (Z)
|
||||
TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
|
||||
blocks_.Add(target);
|
||||
|
||||
target->AppendInstruction(new (Z) GotoInstr(dst));
|
||||
target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId()));
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -1751,11 +1756,12 @@ TargetEntryInstr* IRRegExpMacroAssembler::TargetWithJoinGoto(
|
||||
|
||||
IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto(
|
||||
JoinEntryInstr* dst) {
|
||||
IndirectEntryInstr* target = new (Z) IndirectEntryInstr(
|
||||
block_id_.Alloc(), indirect_id_.Alloc(), kInvalidTryIndex);
|
||||
IndirectEntryInstr* target =
|
||||
new (Z) IndirectEntryInstr(block_id_.Alloc(), indirect_id_.Alloc(),
|
||||
kInvalidTryIndex, GetNextDeoptId());
|
||||
blocks_.Add(target);
|
||||
|
||||
target->AppendInstruction(new (Z) GotoInstr(dst));
|
||||
target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId()));
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -1763,8 +1769,8 @@ IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto(
|
||||
|
||||
void IRRegExpMacroAssembler::CheckPreemption() {
|
||||
TAG();
|
||||
AppendInstruction(new (Z)
|
||||
CheckStackOverflowInstr(TokenPosition::kNoSource, 0));
|
||||
AppendInstruction(new (Z) CheckStackOverflowInstr(TokenPosition::kNoSource, 0,
|
||||
GetNextDeoptId()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -132,6 +132,8 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler {
|
||||
void FinalizeRegistersArray();
|
||||
|
||||
private:
|
||||
intptr_t GetNextDeoptId() const { return thread_->GetNextDeoptId(); }
|
||||
|
||||
// Generate the contents of preset blocks. The entry block is the entry point
|
||||
// of the generated code.
|
||||
void GenerateEntryBlock();
|
||||
@@ -359,6 +361,8 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler {
|
||||
intptr_t next_id;
|
||||
};
|
||||
|
||||
Thread* thread_;
|
||||
|
||||
// Which mode to generate code for (ASCII or UC16).
|
||||
Mode mode_;
|
||||
|
||||
|
||||
+29
-26
@@ -2955,33 +2955,36 @@ RawObject* Simulator::Call(const Code& code,
|
||||
|
||||
{
|
||||
BYTECODE(CreateArrayOpt, A_B_C);
|
||||
const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB]));
|
||||
if (LIKELY(static_cast<uintptr_t>(length) <= Array::kMaxElements)) {
|
||||
const intptr_t fixed_size_plus_alignment_padding =
|
||||
sizeof(RawArray) + kObjectAlignment - 1;
|
||||
const intptr_t instance_size =
|
||||
(fixed_size_plus_alignment_padding + length * kWordSize) &
|
||||
~(kObjectAlignment - 1);
|
||||
const uword start =
|
||||
thread->heap()->new_space()->TryAllocate(instance_size);
|
||||
if (LIKELY(start != 0)) {
|
||||
const intptr_t cid = kArrayCid;
|
||||
uword tags = 0;
|
||||
if (LIKELY(instance_size <= RawObject::SizeTag::kMaxSizeTag)) {
|
||||
tags = RawObject::SizeTag::update(instance_size, tags);
|
||||
if (LIKELY(!FP[rB]->IsHeapObject())) {
|
||||
const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB]));
|
||||
if (LIKELY(static_cast<uintptr_t>(length) <= Array::kMaxElements)) {
|
||||
const intptr_t fixed_size_plus_alignment_padding =
|
||||
sizeof(RawArray) + kObjectAlignment - 1;
|
||||
const intptr_t instance_size =
|
||||
(fixed_size_plus_alignment_padding + length * kWordSize) &
|
||||
~(kObjectAlignment - 1);
|
||||
const uword start =
|
||||
thread->heap()->new_space()->TryAllocate(instance_size);
|
||||
if (LIKELY(start != 0)) {
|
||||
const intptr_t cid = kArrayCid;
|
||||
uword tags = 0;
|
||||
if (LIKELY(instance_size <= RawObject::SizeTag::kMaxSizeTag)) {
|
||||
tags = RawObject::SizeTag::update(instance_size, tags);
|
||||
}
|
||||
tags = RawObject::ClassIdTag::update(cid, tags);
|
||||
*reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
|
||||
*reinterpret_cast<RawObject**>(start + Array::length_offset()) =
|
||||
FP[rB];
|
||||
*reinterpret_cast<RawObject**>(
|
||||
start + Array::type_arguments_offset()) = FP[rC];
|
||||
RawObject** data =
|
||||
reinterpret_cast<RawObject**>(start + Array::data_offset());
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
data[i] = null_value;
|
||||
}
|
||||
FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
|
||||
pc += 4;
|
||||
}
|
||||
tags = RawObject::ClassIdTag::update(cid, tags);
|
||||
*reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
|
||||
*reinterpret_cast<RawObject**>(start + Array::length_offset()) = FP[rB];
|
||||
*reinterpret_cast<RawObject**>(start + Array::type_arguments_offset()) =
|
||||
FP[rC];
|
||||
RawObject** data =
|
||||
reinterpret_cast<RawObject**>(start + Array::data_offset());
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
data[i] = null_value;
|
||||
}
|
||||
FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
|
||||
pc += 4;
|
||||
}
|
||||
}
|
||||
DISPATCH();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// VMOptions=--optimization-counter-threshold=10 --no-use-osr --no-background-compilation --enable_inlining_annotations
|
||||
|
||||
const NeverInline = "NeverInline";
|
||||
|
||||
foo(n) {
|
||||
return new List(n);
|
||||
}
|
||||
|
||||
@NeverInline
|
||||
bar(n) {
|
||||
try {
|
||||
return foo(n);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
main() {
|
||||
for (var i = 0; i < 20; i++) {
|
||||
bar(5);
|
||||
}
|
||||
bar("");
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// VMOptions=--optimization-counter-threshold=10 --no-use-osr --no-background-compilation --enable_inlining_annotations
|
||||
|
||||
const NeverInline = "NeverInline";
|
||||
|
||||
@NeverInline
|
||||
foo(n) {
|
||||
try {
|
||||
return new List(n);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
main() {
|
||||
for (var i = 0; i < 20; i++) {
|
||||
foo(5);
|
||||
}
|
||||
foo("");
|
||||
}
|
||||
Reference in New Issue
Block a user