Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 1317213003: Improve async code in VM by not unnecessarily capturing parameters of async and (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Avoid duplicate aliases Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 last_used_block_id_(0), // 0 is used for the graph entry. 318 last_used_block_id_(0), // 0 is used for the graph entry.
319 try_index_(CatchClauseNode::kInvalidTryIndex), 319 try_index_(CatchClauseNode::kInvalidTryIndex),
320 catch_try_index_(CatchClauseNode::kInvalidTryIndex), 320 catch_try_index_(CatchClauseNode::kInvalidTryIndex),
321 loop_depth_(0), 321 loop_depth_(0),
322 graph_entry_(NULL), 322 graph_entry_(NULL),
323 temp_count_(0), 323 temp_count_(0),
324 args_pushed_(0), 324 args_pushed_(0),
325 nesting_stack_(NULL), 325 nesting_stack_(NULL),
326 osr_id_(osr_id), 326 osr_id_(osr_id),
327 jump_count_(0), 327 jump_count_(0),
328 await_joins_(new(Z) ZoneGrowableArray<JoinEntryInstr*>()), 328 await_joins_(new(Z) ZoneGrowableArray<JoinEntryInstr*>()) { }
329 await_levels_(new(Z) ZoneGrowableArray<intptr_t>()) { }
330 329
331 330
332 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { 331 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
333 graph_entry_->AddCatchEntry(entry); 332 graph_entry_->AddCatchEntry(entry);
334 } 333 }
335 334
336 335
337 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { 336 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
338 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); 337 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
339 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); 338 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id());
(...skipping 1271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 return new(Z) AssertAssignableInstr(token_pos, 1610 return new(Z) AssertAssignableInstr(token_pos,
1612 value, 1611 value,
1613 instantiator, 1612 instantiator,
1614 instantiator_type_arguments, 1613 instantiator_type_arguments,
1615 dst_type, 1614 dst_type,
1616 dst_name, 1615 dst_name,
1617 deopt_id); 1616 deopt_id);
1618 } 1617 }
1619 1618
1620 1619
1621 void EffectGraphVisitor::BuildSyncYieldJump(LocalVariable* old_context,
1622 LocalVariable* iterator_param,
1623 const intptr_t old_ctx_level,
1624 JoinEntryInstr* target) {
1625 // Building a jump consists of the following actions:
1626 // * Load the generator body's iterator parameter (:iterator)
1627 // from the current context into a temporary.
1628 // * Restore the old context from :await_cxt_var.
1629 // * Copy the iterator saved above into the restored context.
1630 // * Append a Goto to the target's join.
1631 ASSERT((iterator_param != NULL) && iterator_param->is_captured());
1632 ASSERT((old_context != NULL) && old_context->is_captured());
1633 // Before restoring the context we need to temporarily save the
1634 // iterator parameter.
1635 LocalVariable* temp_iterator_var =
1636 EnterTempLocalScope(Bind(BuildLoadLocal(*iterator_param)));
1637
1638 // Restore the saved continuation context, i.e. the context that was
1639 // saved into :await_ctx_var before the closure suspended.
1640 BuildRestoreContext(*old_context);
1641
1642 // Store the continuation result and continuation error values into
1643 // the restored context.
1644
1645 // FlowGraphBuilder is at top context level, but the continuation
1646 // target has possibly been recorded in a nested context (old_ctx_level).
1647 // We need to unroll manually here.
1648 intptr_t delta =
1649 old_ctx_level - iterator_param->owner()->context_level();
1650 ASSERT(delta >= 0);
1651 Value* context = Bind(BuildCurrentContext());
1652 while (delta-- > 0) {
1653 context = Bind(new(Z) LoadFieldInstr(
1654 context, Context::parent_offset(), Type::ZoneHandle(Z, Type::null()),
1655 Scanner::kNoSourcePos));
1656 }
1657 LocalVariable* temp_context_var = EnterTempLocalScope(context);
1658
1659 Value* context_val = Bind(new(Z) LoadLocalInstr(*temp_context_var));
1660 Value* store_val = Bind(new(Z) LoadLocalInstr(*temp_iterator_var));
1661 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
1662 Context::variable_offset(iterator_param->index()),
1663 context_val,
1664 store_val,
1665 kEmitStoreBarrier,
1666 Scanner::kNoSourcePos);
1667 Do(store);
1668
1669 Do(ExitTempLocalScope(temp_context_var));
1670 Do(ExitTempLocalScope(temp_iterator_var));
1671
1672 // Goto saved join.
1673 Goto(target);
1674 }
1675
1676
1677 void EffectGraphVisitor::BuildAsyncJump(LocalVariable* old_context,
1678 LocalVariable* continuation_result,
1679 LocalVariable* continuation_error,
1680 LocalVariable* continuation_stack_trace,
1681 const intptr_t old_ctx_level,
1682 JoinEntryInstr* target) {
1683 // Building a jump consists of the following actions:
1684 // * Load the current continuation result parameter (:async_result)
1685 // and continuation error parameter (:async_error_param) from
1686 // the current context into temporaries.
1687 // * Restore the old context from :await_cxt_var.
1688 // * Copy the result and error parameters saved above into the restored
1689 // context.
1690 // * Append a Goto to the target's join.
1691 ASSERT((continuation_result != NULL) && continuation_result->is_captured());
1692 ASSERT((continuation_error != NULL) && continuation_error->is_captured());
1693 ASSERT((old_context != NULL) && old_context->is_captured());
1694 // Before restoring the continuation context we need to temporary save the
1695 // result and error parameter.
1696 LocalVariable* temp_result_var =
1697 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_result)));
1698 LocalVariable* temp_error_var =
1699 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_error)));
1700 LocalVariable* temp_stack_trace_var =
1701 EnterTempLocalScope(Bind(BuildLoadLocal(*continuation_stack_trace)));
1702
1703 // Restore the saved continuation context, i.e. the context that was
1704 // saved into :await_ctx_var before the closure suspended.
1705 BuildRestoreContext(*old_context);
1706
1707 // Store the continuation result and continuation error values into
1708 // the restored context.
1709
1710 // FlowGraphBuilder is at top context level, but the await target has possibly
1711 // been recorded in a nested context (old_ctx_level). We need to unroll
1712 // manually here.
1713 intptr_t delta =
1714 old_ctx_level - continuation_result->owner()->context_level();
1715 ASSERT(delta >= 0);
1716 Value* context = Bind(BuildCurrentContext());
1717 while (delta-- > 0) {
1718 context = Bind(new(Z) LoadFieldInstr(
1719 context, Context::parent_offset(), Type::ZoneHandle(Z, Type::null()),
1720 Scanner::kNoSourcePos));
1721 }
1722 LocalVariable* temp_context_var = EnterTempLocalScope(context);
1723
1724 Value* context_val = Bind(new(Z) LoadLocalInstr(*temp_context_var));
1725 Value* store_val = Bind(new(Z) LoadLocalInstr(*temp_result_var));
1726 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
1727 Context::variable_offset(continuation_result->index()),
1728 context_val,
1729 store_val,
1730 kEmitStoreBarrier,
1731 Scanner::kNoSourcePos);
1732 Do(store);
1733 context_val = Bind(new(Z) LoadLocalInstr(*temp_context_var));
1734 store_val = Bind(new(Z) LoadLocalInstr(*temp_error_var));
1735 StoreInstanceFieldInstr* store2 = new(Z) StoreInstanceFieldInstr(
1736 Context::variable_offset(continuation_error->index()),
1737 context_val,
1738 store_val,
1739 kEmitStoreBarrier,
1740 Scanner::kNoSourcePos);
1741 Do(store2);
1742
1743 context_val = Bind(new(Z) LoadLocalInstr(*temp_context_var));
1744 store_val = Bind(new(Z) LoadLocalInstr(*temp_stack_trace_var));
1745 StoreInstanceFieldInstr* store3 = new(Z) StoreInstanceFieldInstr(
1746 Context::variable_offset(continuation_stack_trace->index()),
1747 context_val,
1748 store_val,
1749 kEmitStoreBarrier,
1750 Scanner::kNoSourcePos);
1751 Do(store3);
1752
1753 Do(ExitTempLocalScope(temp_context_var));
1754 Do(ExitTempLocalScope(temp_stack_trace_var));
1755 Do(ExitTempLocalScope(temp_error_var));
1756 Do(ExitTempLocalScope(temp_result_var));
1757
1758 // Goto saved join.
1759 Goto(target);
1760 }
1761
1762
1763 // Used for type casts and to test assignments. 1620 // Used for type casts and to test assignments.
1764 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, 1621 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos,
1765 Value* value, 1622 Value* value,
1766 const AbstractType& dst_type, 1623 const AbstractType& dst_type,
1767 const String& dst_name) { 1624 const String& dst_name) {
1768 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { 1625 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) {
1769 return value; 1626 return value;
1770 } 1627 }
1771 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); 1628 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name));
1772 } 1629 }
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after
2485 ASSERT(jump_count >= 0); 2342 ASSERT(jump_count >= 0);
2486 // Sanity check that we always add a JoinEntryInstr before adding a new 2343 // Sanity check that we always add a JoinEntryInstr before adding a new
2487 // state. 2344 // state.
2488 ASSERT(jump_count == owner()->await_joins()->length()); 2345 ASSERT(jump_count == owner()->await_joins()->length());
2489 // Store the counter in :await_jump_var. 2346 // Store the counter in :await_jump_var.
2490 Value* jump_val = Bind(new(Z) ConstantInstr( 2347 Value* jump_val = Bind(new(Z) ConstantInstr(
2491 Smi::ZoneHandle(Z, Smi::New(jump_count)))); 2348 Smi::ZoneHandle(Z, Smi::New(jump_count))));
2492 Do(BuildStoreLocal(*jump_var, jump_val)); 2349 Do(BuildStoreLocal(*jump_var, jump_val));
2493 // Save the current context for resuming. 2350 // Save the current context for resuming.
2494 BuildSaveContext(*ctx_var); 2351 BuildSaveContext(*ctx_var);
2495 owner()->await_levels()->Add(owner()->context_level());
2496 } 2352 }
2497 2353
2498 2354
2499 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { 2355 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const {
2500 return kFirstLocalSlotFromFp 2356 return kFirstLocalSlotFromFp
2501 - owner()->num_stack_locals() 2357 - owner()->num_stack_locals()
2502 - owner()->num_copied_params() 2358 - owner()->num_copied_params()
2503 - owner()->args_pushed() 2359 - owner()->args_pushed()
2504 - owner()->temp_count() + 1; 2360 - owner()->temp_count() + 1;
2505 } 2361 }
(...skipping 1886 matching lines...) Expand 10 before | Expand all | Expand 10 after
4392 Scanner::kNoSourcePos, 4248 Scanner::kNoSourcePos,
4393 Token::kEQ, 4249 Token::kEQ,
4394 load_jump_count, 4250 load_jump_count,
4395 new(Z) LiteralNode( 4251 new(Z) LiteralNode(
4396 Scanner::kNoSourcePos, Smi::ZoneHandle(Z, Smi::New(i)))); 4252 Scanner::kNoSourcePos, Smi::ZoneHandle(Z, Smi::New(i))));
4397 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos); 4253 TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
4398 check_jump_count->Visit(&for_test); 4254 check_jump_count->Visit(&for_test);
4399 EffectGraphVisitor for_true(owner()); 4255 EffectGraphVisitor for_true(owner());
4400 EffectGraphVisitor for_false(owner()); 4256 EffectGraphVisitor for_false(owner());
4401 4257
4402 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { 4258 // Build async jump or sync yield jump.
4403 LocalVariable* result_param = 4259 ASSERT(function.IsAsyncClosure() ||
4404 top_scope->LookupVariable(Symbols::AsyncOperationParam(), false); 4260 function.IsAsyncGenClosure() ||
4405 LocalVariable* error_param = 4261 function.IsSyncGenClosure());
4406 top_scope->LookupVariable(Symbols::AsyncOperationErrorParam(), 4262
4407 false); 4263 // Restore the saved continuation context, i.e. the context that was
4408 LocalVariable* stack_trace_param = 4264 // saved into :await_ctx_var before the closure suspended.
4409 top_scope->LookupVariable(Symbols::AsyncOperationStackTraceParam(), 4265 for_true.BuildRestoreContext(*old_context);
4410 false); 4266
4411 for_true.BuildAsyncJump(old_context, 4267 // Goto saved join.
4412 result_param, 4268 for_true.Goto((*owner()->await_joins())[i]);
4413 error_param,
4414 stack_trace_param,
4415 (*owner()->await_levels())[i],
4416 (*owner()->await_joins())[i]);
4417 } else {
4418 ASSERT(function.IsSyncGenClosure());
4419 LocalVariable* iterator_param =
4420 top_scope->LookupVariable(Symbols::IteratorParameter(), false);
4421 for_true.BuildSyncYieldJump(old_context,
4422 iterator_param,
4423 (*owner()->await_levels())[i],
4424 (*owner()->await_joins())[i]);
4425 }
4426 4269
4427 Join(for_test, for_true, for_false); 4270 Join(for_test, for_true, for_false);
4428 if (i == 0) { 4271 if (i == 0) {
4429 // Manually link up the preamble start. 4272 // Manually link up the preamble start.
4430 preamble_start->previous()->set_next(for_test.entry()); 4273 preamble_start->previous()->set_next(for_test.entry());
4431 for_test.entry()->set_previous(preamble_start->previous()); 4274 for_test.entry()->set_previous(preamble_start->previous());
4432 } 4275 }
4433 if (i == (num_await_states - 1)) { 4276 if (i == (num_await_states - 1)) {
4434 // Link up preamble end. 4277 // Link up preamble end.
4435 if (exit_ == NULL) { 4278 if (exit_ == NULL) {
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
4832 Report::MessageF(Report::kBailout, 4675 Report::MessageF(Report::kBailout,
4833 Script::Handle(function.script()), 4676 Script::Handle(function.script()),
4834 function.token_pos(), 4677 function.token_pos(),
4835 "FlowGraphBuilder Bailout: %s %s", 4678 "FlowGraphBuilder Bailout: %s %s",
4836 String::Handle(function.name()).ToCString(), 4679 String::Handle(function.name()).ToCString(),
4837 reason); 4680 reason);
4838 UNREACHABLE(); 4681 UNREACHABLE();
4839 } 4682 }
4840 4683
4841 } // namespace dart 4684 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698