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

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

Issue 17233003: Reapply "Initial implementation of on-stack replacement (OSR)." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/flow_graph_compiler.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/code_descriptors.h" 10 #include "vm/code_descriptors.h"
10 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
11 #include "vm/flags.h" 12 #include "vm/flags.h"
12 #include "vm/flow_graph_compiler.h" 13 #include "vm/flow_graph_compiler.h"
13 #include "vm/il_printer.h" 14 #include "vm/il_printer.h"
14 #include "vm/intermediate_language.h" 15 #include "vm/intermediate_language.h"
15 #include "vm/longjump.h" 16 #include "vm/longjump.h"
16 #include "vm/object_store.h" 17 #include "vm/object_store.h"
17 #include "vm/os.h" 18 #include "vm/os.h"
18 #include "vm/parser.h" 19 #include "vm/parser.h"
(...skipping 17 matching lines...) Expand all
36 37
37 static const String& PrivateCoreLibName(const String& str) { 38 static const String& PrivateCoreLibName(const String& str) {
38 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 39 const Library& core_lib = Library::Handle(Library::CoreLibrary());
39 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); 40 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str));
40 return private_name; 41 return private_name;
41 } 42 }
42 43
43 44
44 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function, 45 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function,
45 const Array& ic_data_array, 46 const Array& ic_data_array,
46 InlineExitCollector* exit_collector) 47 InlineExitCollector* exit_collector,
48 intptr_t osr_id)
47 : parsed_function_(parsed_function), 49 : parsed_function_(parsed_function),
48 ic_data_array_(ic_data_array), 50 ic_data_array_(ic_data_array),
49 num_copied_params_(parsed_function->num_copied_params()), 51 num_copied_params_(parsed_function->num_copied_params()),
50 // All parameters are copied if any parameter is. 52 // All parameters are copied if any parameter is.
51 num_non_copied_params_((num_copied_params_ == 0) 53 num_non_copied_params_((num_copied_params_ == 0)
52 ? parsed_function->function().num_fixed_parameters() 54 ? parsed_function->function().num_fixed_parameters()
53 : 0), 55 : 0),
54 num_stack_locals_(parsed_function->num_stack_locals()), 56 num_stack_locals_(parsed_function->num_stack_locals()),
55 exit_collector_(exit_collector), 57 exit_collector_(exit_collector),
56 last_used_block_id_(0), // 0 is used for the graph entry. 58 last_used_block_id_(0), // 0 is used for the graph entry.
57 context_level_(0), 59 context_level_(0),
58 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), 60 last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
59 try_index_(CatchClauseNode::kInvalidTryIndex), 61 try_index_(CatchClauseNode::kInvalidTryIndex),
60 graph_entry_(NULL), 62 graph_entry_(NULL),
61 args_pushed_(0) { } 63 args_pushed_(0),
64 osr_id_(osr_id) { }
62 65
63 66
64 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { 67 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
65 graph_entry_->AddCatchEntry(entry); 68 graph_entry_->AddCatchEntry(entry);
66 } 69 }
67 70
68 71
69 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { 72 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
70 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); 73 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
71 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); 74 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id());
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 470 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
468 true_exit->Goto(join); 471 true_exit->Goto(join);
469 false_exit->Goto(join); 472 false_exit->Goto(join);
470 exit_ = join; 473 exit_ = join;
471 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); 474 ASSERT(true_fragment.temp_index() == false_fragment.temp_index());
472 temp_index_ = true_fragment.temp_index(); 475 temp_index_ = true_fragment.temp_index();
473 } 476 }
474 } 477 }
475 478
476 479
477 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, 480 void EffectGraphVisitor::TieLoop(intptr_t token_pos,
481 const TestGraphVisitor& test_fragment,
478 const EffectGraphVisitor& body_fragment) { 482 const EffectGraphVisitor& body_fragment) {
479 // We have: a test graph fragment with zero, one, or two available exits; 483 // We have: a test graph fragment with zero, one, or two available exits;
480 // and an effect graph fragment with zero or one available exits. We want 484 // and an effect graph fragment with zero or one available exits. We want
481 // to append the 'while loop' consisting of the test graph fragment as 485 // to append the 'while loop' consisting of the test graph fragment as
482 // condition and the effect graph fragment as body. 486 // condition and the effect graph fragment as body.
483 ASSERT(is_open()); 487 ASSERT(is_open());
484 488
485 // 1. Connect the body to the test if it is reachable, and if so record 489 // 1. Connect the body to the test if it is reachable, and if so record
486 // its exit (if any). 490 // its exit (if any).
487 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); 491 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor();
488 Instruction* body_exit = AppendFragment(body_entry, body_fragment); 492 Instruction* body_exit = AppendFragment(body_entry, body_fragment);
489 493
490 // 2. Connect the test to this graph, including the body if reachable and 494 // 2. Connect the test to this graph, including the body if reachable and
491 // using a fresh join node if the body is reachable and has an open exit. 495 // using a fresh join node if the body is reachable and has an open exit.
492 if (body_exit == NULL) { 496 if (body_exit == NULL) {
493 Append(test_fragment); 497 Append(test_fragment);
494 } else { 498 } else {
495 JoinEntryInstr* join = 499 JoinEntryInstr* join =
496 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 500 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
497 join->LinkTo(test_fragment.entry()); 501 CheckStackOverflowInstr* check =
502 new CheckStackOverflowInstr(token_pos, true);
503 join->LinkTo(check);
504 check->LinkTo(test_fragment.entry());
498 Goto(join); 505 Goto(join);
499 body_exit->Goto(join); 506 body_exit->Goto(join);
500 } 507 }
501 508
502 // 3. Set the exit to the graph to be the false successor of the test, a 509 // 3. Set the exit to the graph to be the false successor of the test, a
503 // fresh target node 510 // fresh target node
504
505 exit_ = test_fragment.CreateFalseSuccessor(); 511 exit_ = test_fragment.CreateFalseSuccessor();
506 } 512 }
507 513
508 514
509 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { 515 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) {
510 owner_->add_args_pushed(1); 516 owner_->add_args_pushed(1);
511 PushArgumentInstr* result = new PushArgumentInstr(value); 517 PushArgumentInstr* result = new PushArgumentInstr(value);
512 AddInstruction(result); 518 AddInstruction(result);
513 return result; 519 return result;
514 } 520 }
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 // f) loop-exit-target 1601 // f) loop-exit-target
1596 // g) break-join (optional) 1602 // g) break-join (optional)
1597 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { 1603 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
1598 TestGraphVisitor for_test(owner(), 1604 TestGraphVisitor for_test(owner(),
1599 temp_index(), 1605 temp_index(),
1600 node->condition()->token_pos()); 1606 node->condition()->token_pos());
1601 node->condition()->Visit(&for_test); 1607 node->condition()->Visit(&for_test);
1602 ASSERT(!for_test.is_empty()); // Language spec. 1608 ASSERT(!for_test.is_empty()); // Language spec.
1603 1609
1604 EffectGraphVisitor for_body(owner(), temp_index()); 1610 EffectGraphVisitor for_body(owner(), temp_index());
1605 for_body.AddInstruction(
1606 new CheckStackOverflowInstr(node->token_pos()));
1607 node->body()->Visit(&for_body); 1611 node->body()->Visit(&for_body);
1608 1612
1609 // Labels are set after body traversal. 1613 // Labels are set after body traversal.
1610 SourceLabel* lbl = node->label(); 1614 SourceLabel* lbl = node->label();
1611 ASSERT(lbl != NULL); 1615 ASSERT(lbl != NULL);
1612 JoinEntryInstr* join = lbl->join_for_continue(); 1616 JoinEntryInstr* join = lbl->join_for_continue();
1613 if (join != NULL) { 1617 if (join != NULL) {
1614 if (for_body.is_open()) for_body.Goto(join); 1618 if (for_body.is_open()) for_body.Goto(join);
1615 for_body.exit_ = join; 1619 for_body.exit_ = join;
1616 } 1620 }
1617 TieLoop(for_test, for_body); 1621 TieLoop(node->token_pos(), for_test, for_body);
1618 join = lbl->join_for_break(); 1622 join = lbl->join_for_break();
1619 if (join != NULL) { 1623 if (join != NULL) {
1620 Goto(join); 1624 Goto(join);
1621 exit_ = join; 1625 exit_ = join;
1622 } 1626 }
1623 } 1627 }
1624 1628
1625 1629
1626 // The fragment is composed as follows: 1630 // The fragment is composed as follows:
1627 // a) body-entry-join 1631 // a) body-entry-join
1628 // b) [ body ] 1632 // b) [ body ]
1629 // c) test-entry (continue-join or body-exit-target) 1633 // c) test-entry (continue-join or body-exit-target)
1630 // d) [ test-entry ] -> (back-target, loop-exit-target) 1634 // d) [ test-entry ] -> (back-target, loop-exit-target)
1631 // e) back-target -> (body-entry-join) 1635 // e) back-target -> (body-entry-join)
1632 // f) loop-exit-target 1636 // f) loop-exit-target
1633 // g) break-join 1637 // g) break-join
1634 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { 1638 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
1635 // Traverse body first in order to generate continue and break labels. 1639 // Traverse body first in order to generate continue and break labels.
1636 EffectGraphVisitor for_body(owner(), temp_index()); 1640 EffectGraphVisitor for_body(owner(), temp_index());
1637 for_body.AddInstruction(
1638 new CheckStackOverflowInstr(node->token_pos()));
1639 node->body()->Visit(&for_body); 1641 node->body()->Visit(&for_body);
1640 1642
1641 TestGraphVisitor for_test(owner(), 1643 TestGraphVisitor for_test(owner(),
1642 temp_index(), 1644 temp_index(),
1643 node->condition()->token_pos()); 1645 node->condition()->token_pos());
1644 node->condition()->Visit(&for_test); 1646 node->condition()->Visit(&for_test);
1645 ASSERT(is_open()); 1647 ASSERT(is_open());
1646 1648
1647 // Tie do-while loop (test is after the body). 1649 // Tie do-while loop (test is after the body).
1648 JoinEntryInstr* body_entry_join = 1650 JoinEntryInstr* body_entry_join =
1649 new JoinEntryInstr(owner()->AllocateBlockId(), 1651 new JoinEntryInstr(owner()->AllocateBlockId(),
1650 owner()->try_index()); 1652 owner()->try_index());
1651 Goto(body_entry_join); 1653 Goto(body_entry_join);
1652 Instruction* body_exit = AppendFragment(body_entry_join, for_body); 1654 Instruction* body_exit = AppendFragment(body_entry_join, for_body);
1653 1655
1654 JoinEntryInstr* join = node->label()->join_for_continue(); 1656 JoinEntryInstr* join = node->label()->join_for_continue();
1655 if ((body_exit != NULL) || (join != NULL)) { 1657 if ((body_exit != NULL) || (join != NULL)) {
1656 if (join == NULL) { 1658 if (join == NULL) {
1657 join = new JoinEntryInstr(owner()->AllocateBlockId(), 1659 join = new JoinEntryInstr(owner()->AllocateBlockId(),
1658 owner()->try_index()); 1660 owner()->try_index());
1659 } 1661 }
1660 join->LinkTo(for_test.entry()); 1662 CheckStackOverflowInstr* check =
1663 new CheckStackOverflowInstr(node->token_pos(), true);
1664 join->LinkTo(check);
1665 check->LinkTo(for_test.entry());
1661 if (body_exit != NULL) { 1666 if (body_exit != NULL) {
1662 body_exit->Goto(join); 1667 body_exit->Goto(join);
1663 } 1668 }
1664 } 1669 }
1665 1670
1666 for_test.IfTrueGoto(body_entry_join); 1671 for_test.IfTrueGoto(body_entry_join);
1667 join = node->label()->join_for_break(); 1672 join = node->label()->join_for_break();
1668 if (join == NULL) { 1673 if (join == NULL) {
1669 exit_ = for_test.CreateFalseSuccessor(); 1674 exit_ = for_test.CreateFalseSuccessor();
1670 } else { 1675 } else {
(...skipping 16 matching lines...) Expand all
1687 // h) loop-exit-target 1692 // h) loop-exit-target
1688 // i) break-join 1693 // i) break-join
1689 void EffectGraphVisitor::VisitForNode(ForNode* node) { 1694 void EffectGraphVisitor::VisitForNode(ForNode* node) {
1690 EffectGraphVisitor for_initializer(owner(), temp_index()); 1695 EffectGraphVisitor for_initializer(owner(), temp_index());
1691 node->initializer()->Visit(&for_initializer); 1696 node->initializer()->Visit(&for_initializer);
1692 Append(for_initializer); 1697 Append(for_initializer);
1693 ASSERT(is_open()); 1698 ASSERT(is_open());
1694 1699
1695 // Compose body to set any jump labels. 1700 // Compose body to set any jump labels.
1696 EffectGraphVisitor for_body(owner(), temp_index()); 1701 EffectGraphVisitor for_body(owner(), temp_index());
1697 for_body.AddInstruction(
1698 new CheckStackOverflowInstr(node->token_pos()));
1699 node->body()->Visit(&for_body); 1702 node->body()->Visit(&for_body);
1700 1703
1701 // Join loop body, increment and compute their end instruction.
1702 ASSERT(!for_body.is_empty());
1703 Instruction* loop_increment_end = NULL;
1704 EffectGraphVisitor for_increment(owner(), temp_index()); 1704 EffectGraphVisitor for_increment(owner(), temp_index());
1705 node->increment()->Visit(&for_increment); 1705 node->increment()->Visit(&for_increment);
1706
1707 // Join the loop body and increment and then tie the loop.
1706 JoinEntryInstr* join = node->label()->join_for_continue(); 1708 JoinEntryInstr* join = node->label()->join_for_continue();
1707 if (join != NULL) { 1709 if ((join != NULL) || for_body.is_open()) {
1708 // Insert the join between the body and increment.
1709 if (for_body.is_open()) for_body.Goto(join);
1710 loop_increment_end = AppendFragment(join, for_increment);
1711 ASSERT(loop_increment_end != NULL);
1712 } else if (for_body.is_open()) {
1713 // Do not insert an extra basic block.
1714 for_body.Append(for_increment);
1715 loop_increment_end = for_body.exit();
1716 // 'for_body' contains at least the stack check.
1717 ASSERT(loop_increment_end != NULL);
1718 } else {
1719 loop_increment_end = NULL;
1720 }
1721
1722 // 'loop_increment_end' is NULL only if there is no join for continue and the
1723 // body is not open, i.e., no backward branch exists.
1724 if (loop_increment_end != NULL) {
1725 JoinEntryInstr* loop_start = 1710 JoinEntryInstr* loop_start =
1726 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 1711 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
1712 if (join != NULL) {
1713 if (for_body.is_open()) for_body.Goto(join);
1714 AppendFragment(join, for_increment);
1715 for_increment.Goto(loop_start);
1716 } else {
1717 for_body.Append(for_increment);
1718 for_body.Goto(loop_start);
1719 }
1727 Goto(loop_start); 1720 Goto(loop_start);
1728 loop_increment_end->Goto(loop_start);
1729 exit_ = loop_start; 1721 exit_ = loop_start;
1722 AddInstruction(new CheckStackOverflowInstr(node->token_pos(), true));
1730 } 1723 }
1731 1724
1732 if (node->condition() == NULL) { 1725 if (node->condition() == NULL) {
1733 // Endless loop, no test. 1726 // Endless loop, no test.
1734 JoinEntryInstr* body_entry = 1727 JoinEntryInstr* body_entry =
1735 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 1728 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
1736 AppendFragment(body_entry, for_body); 1729 AppendFragment(body_entry, for_body);
1737 Goto(body_entry); 1730 Goto(body_entry);
1738 if (node->label()->join_for_break() != NULL) { 1731 if (node->label()->join_for_break() != NULL) {
1739 // Control flow of ForLoop continues into join_for_break. 1732 // Control flow of ForLoop continues into join_for_break.
(...skipping 1716 matching lines...) Expand 10 before | Expand all | Expand 10 after
3456 AppendFragment(finally_entry, for_finally_block); 3449 AppendFragment(finally_entry, for_finally_block);
3457 exit_ = for_finally_block.exit_; 3450 exit_ = for_finally_block.exit_;
3458 } 3451 }
3459 3452
3460 3453
3461 FlowGraph* FlowGraphBuilder::BuildGraph() { 3454 FlowGraph* FlowGraphBuilder::BuildGraph() {
3462 if (FLAG_print_ast) { 3455 if (FLAG_print_ast) {
3463 // Print the function ast before IL generation. 3456 // Print the function ast before IL generation.
3464 AstPrinter::PrintFunctionNodes(*parsed_function()); 3457 AstPrinter::PrintFunctionNodes(*parsed_function());
3465 } 3458 }
3466 // Compilation can be nested, preserve the computation-id.
3467 const Function& function = parsed_function()->function(); 3459 const Function& function = parsed_function()->function();
3468 TargetEntryInstr* normal_entry = 3460 TargetEntryInstr* normal_entry =
3469 new TargetEntryInstr(AllocateBlockId(), 3461 new TargetEntryInstr(AllocateBlockId(),
3470 CatchClauseNode::kInvalidTryIndex); 3462 CatchClauseNode::kInvalidTryIndex);
3471 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry); 3463 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_);
3472 EffectGraphVisitor for_effect(this, 0); 3464 EffectGraphVisitor for_effect(this, 0);
3473 // This check may be deleted if the generated code is leaf. 3465 // This check may be deleted if the generated code is leaf.
3474 CheckStackOverflowInstr* check = 3466 CheckStackOverflowInstr* check =
3475 new CheckStackOverflowInstr(function.token_pos()); 3467 new CheckStackOverflowInstr(function.token_pos(), false);
3476 // If we are inlining don't actually attach the stack check. We must still 3468 // If we are inlining don't actually attach the stack check. We must still
3477 // create the stack check in order to allocate a deopt id. 3469 // create the stack check in order to allocate a deopt id.
3478 if (!IsInlining()) for_effect.AddInstruction(check); 3470 if (!IsInlining()) for_effect.AddInstruction(check);
3479 parsed_function()->node_sequence()->Visit(&for_effect); 3471 parsed_function()->node_sequence()->Visit(&for_effect);
3480 AppendFragment(normal_entry, for_effect); 3472 AppendFragment(normal_entry, for_effect);
3481 // Check that the graph is properly terminated. 3473 // Check that the graph is properly terminated.
3482 ASSERT(!for_effect.is_open()); 3474 ASSERT(!for_effect.is_open());
3475
3476 // When compiling for OSR, use a depth first search to prune instructions
3477 // unreachable from the OSR entry. Catch entries are not (yet) properly
3478 // recognized as reachable.
3479 if (osr_id_ != Isolate::kNoDeoptId) {
3480 if (graph_entry_->SuccessorCount() > 1) {
3481 Bailout("try/catch when compiling for OSR");
3482 }
3483 PruneUnreachable();
3484 }
3485
3483 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); 3486 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_);
3484 return graph; 3487 return graph;
3485 } 3488 }
3486 3489
3487 3490
3491 void FlowGraphBuilder::PruneUnreachable() {
3492 ASSERT(osr_id_ != Isolate::kNoDeoptId);
3493 BitVector* block_marks = new BitVector(last_used_block_id_ + 1);
3494 bool found = graph_entry_->PruneUnreachable(this, graph_entry_, osr_id_,
3495 block_marks);
3496 ASSERT(found);
3497 }
3498
3499
3488 void FlowGraphBuilder::Bailout(const char* reason) { 3500 void FlowGraphBuilder::Bailout(const char* reason) {
3489 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; 3501 const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
3490 const char* function_name = parsed_function_->function().ToCString(); 3502 const char* function_name = parsed_function_->function().ToCString();
3491 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3503 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3492 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3504 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3493 OS::SNPrint(chars, len, kFormat, function_name, reason); 3505 OS::SNPrint(chars, len, kFormat, function_name, reason);
3494 const Error& error = Error::Handle( 3506 const Error& error = Error::Handle(
3495 LanguageError::New(String::Handle(String::New(chars)))); 3507 LanguageError::New(String::Handle(String::New(chars))));
3496 Isolate::Current()->long_jump_base()->Jump(1, error); 3508 Isolate::Current()->long_jump_base()->Jump(1, error);
3497 } 3509 }
3498 3510
3499 3511
3500 } // namespace dart 3512 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698