LCOV - code coverage report
Current view: top level - src/compiler - schedule.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 188 227 82.8 %
Date: 2017-10-20 Functions: 34 44 77.3 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/schedule.h"
       6             : 
       7             : #include "src/compiler/node-properties.h"
       8             : #include "src/compiler/node.h"
       9             : #include "src/ostreams.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : namespace compiler {
      14             : 
      15     1722087 : BasicBlock::BasicBlock(Zone* zone, Id id)
      16             :     : loop_number_(-1),
      17             :       rpo_number_(-1),
      18             :       deferred_(false),
      19             :       dominator_depth_(-1),
      20             :       dominator_(nullptr),
      21             :       rpo_next_(nullptr),
      22             :       loop_header_(nullptr),
      23             :       loop_end_(nullptr),
      24             :       loop_depth_(0),
      25             :       control_(kNone),
      26             :       control_input_(nullptr),
      27             :       nodes_(zone),
      28             :       successors_(zone),
      29             :       predecessors_(zone),
      30             : #if DEBUG
      31             :       debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
      32             : #endif
      33    35222256 :       id_(id) {
      34     1722087 : }
      35             : 
      36        1438 : bool BasicBlock::LoopContains(BasicBlock* block) const {
      37             :   // RPO numbers must be initialized.
      38             :   DCHECK_LE(0, rpo_number_);
      39             :   DCHECK_LE(0, block->rpo_number_);
      40        1438 :   if (loop_end_ == nullptr) return false;  // This is not a loop.
      41        2876 :   return block->rpo_number_ >= rpo_number_ &&
      42        2876 :          block->rpo_number_ < loop_end_->rpo_number_;
      43             : }
      44             : 
      45             : 
      46           0 : void BasicBlock::AddSuccessor(BasicBlock* successor) {
      47    18929377 :   successors_.push_back(successor);
      48           0 : }
      49             : 
      50             : 
      51           0 : void BasicBlock::AddPredecessor(BasicBlock* predecessor) {
      52    18538498 :   predecessors_.push_back(predecessor);
      53           0 : }
      54             : 
      55             : 
      56   100752089 : void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); }
      57             : 
      58             : 
      59           0 : void BasicBlock::set_control(Control control) {
      60    14158297 :   control_ = control;
      61           0 : }
      62             : 
      63             : 
      64           0 : void BasicBlock::set_control_input(Node* control_input) {
      65     7164944 :   control_input_ = control_input;
      66           0 : }
      67             : 
      68             : 
      69    16150261 : void BasicBlock::set_loop_depth(int32_t loop_depth) {
      70    16150261 :   loop_depth_ = loop_depth;
      71    16150261 : }
      72             : 
      73             : 
      74    76005099 : void BasicBlock::set_rpo_number(int32_t rpo_number) {
      75    76005099 :   rpo_number_ = rpo_number;
      76    76005099 : }
      77             : 
      78             : 
      79      136748 : void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }
      80             : 
      81             : 
      82    16150169 : void BasicBlock::set_loop_header(BasicBlock* loop_header) {
      83    16150169 :   loop_header_ = loop_header;
      84    16150169 : }
      85             : 
      86             : 
      87             : // static
      88   969581531 : BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
      89   680859162 :   while (b1 != b2) {
      90   462622172 :     if (b1->dominator_depth() < b2->dominator_depth()) {
      91             :       b2 = b2->dominator();
      92             :     } else {
      93             :       b1 = b1->dominator();
      94             :     }
      95             :   }
      96   109118495 :   return b1;
      97             : }
      98             : 
      99           0 : void BasicBlock::Print() { OFStream(stdout) << this; }
     100             : 
     101           0 : std::ostream& operator<<(std::ostream& os, const BasicBlock& block) {
     102           0 :   os << "B" << block.id();
     103             : #if DEBUG
     104             :   AssemblerDebugInfo info = block.debug_info();
     105             :   if (info.name) os << info;
     106             :   // Print predecessor blocks for better debugging.
     107             :   const int kMaxDisplayedBlocks = 4;
     108             :   int i = 0;
     109             :   const BasicBlock* current_block = &block;
     110             :   while (current_block->PredecessorCount() > 0 && i++ < kMaxDisplayedBlocks) {
     111             :     current_block = current_block->predecessors().front();
     112             :     os << " <= B" << current_block->id();
     113             :     info = current_block->debug_info();
     114             :     if (info.name) os << info;
     115             :   }
     116             : #endif
     117           0 :   return os;
     118             : }
     119             : 
     120           0 : std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
     121           0 :   switch (c) {
     122             :     case BasicBlock::kNone:
     123           0 :       return os << "none";
     124             :     case BasicBlock::kGoto:
     125           0 :       return os << "goto";
     126             :     case BasicBlock::kCall:
     127           0 :       return os << "call";
     128             :     case BasicBlock::kBranch:
     129           0 :       return os << "branch";
     130             :     case BasicBlock::kSwitch:
     131           0 :       return os << "switch";
     132             :     case BasicBlock::kDeoptimize:
     133           0 :       return os << "deoptimize";
     134             :     case BasicBlock::kTailCall:
     135           0 :       return os << "tailcall";
     136             :     case BasicBlock::kReturn:
     137           0 :       return os << "return";
     138             :     case BasicBlock::kThrow:
     139           0 :       return os << "throw";
     140             :   }
     141           0 :   UNREACHABLE();
     142             : }
     143             : 
     144             : 
     145           0 : std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) {
     146           0 :   return os << id.ToSize();
     147             : }
     148             : 
     149             : 
     150     1725514 : Schedule::Schedule(Zone* zone, size_t node_count_hint)
     151             :     : zone_(zone),
     152             :       all_blocks_(zone),
     153             :       nodeid_to_block_(zone),
     154             :       rpo_order_(zone),
     155     1725514 :       start_(NewBasicBlock()),
     156     3451050 :       end_(NewBasicBlock()) {
     157     1725555 :   nodeid_to_block_.reserve(node_count_hint);
     158     1725535 : }
     159             : 
     160             : 
     161   284182637 : BasicBlock* Schedule::block(Node* node) const {
     162   568365273 :   if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) {
     163   565060558 :     return nodeid_to_block_[node->id()];
     164             :   }
     165             :   return nullptr;
     166             : }
     167             : 
     168             : 
     169   360753371 : bool Schedule::IsScheduled(Node* node) {
     170   721506742 :   if (node->id() >= nodeid_to_block_.size()) return false;
     171   348371900 :   return nodeid_to_block_[node->id()] != nullptr;
     172             : }
     173             : 
     174             : 
     175    13799790 : BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) {
     176             :   DCHECK(block_id.ToSize() < all_blocks_.size());
     177    27599580 :   return all_blocks_[block_id.ToSize()];
     178             : }
     179             : 
     180             : 
     181           1 : bool Schedule::SameBasicBlock(Node* a, Node* b) const {
     182             :   BasicBlock* block = this->block(a);
     183           2 :   return block != nullptr && block == this->block(b);
     184             : }
     185             : 
     186             : 
     187    15889026 : BasicBlock* Schedule::NewBasicBlock() {
     188             :   BasicBlock* block = new (zone_)
     189    63556134 :       BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size()));
     190    15889041 :   all_blocks_.push_back(block);
     191    15889230 :   return block;
     192             : }
     193             : 
     194             : 
     195    69004971 : void Schedule::PlanNode(BasicBlock* block, Node* node) {
     196    69004971 :   if (FLAG_trace_turbo_scheduler) {
     197           0 :     OFStream os(stdout);
     198           0 :     os << "Planning #" << node->id() << ":" << node->op()->mnemonic()
     199           0 :        << " for future add to B" << block->id() << "\n";
     200             :   }
     201             :   DCHECK_NULL(this->block(node));
     202    69004971 :   SetBlockForNode(block, node);
     203    69005193 : }
     204             : 
     205             : 
     206   100744990 : void Schedule::AddNode(BasicBlock* block, Node* node) {
     207   100744990 :   if (FLAG_trace_turbo_scheduler) {
     208           0 :     OFStream os(stdout);
     209           0 :     os << "Adding #" << node->id() << ":" << node->op()->mnemonic() << " to B"
     210           0 :        << block->id() << "\n";
     211             :   }
     212             :   DCHECK(this->block(node) == nullptr || this->block(node) == block);
     213             :   block->AddNode(node);
     214   100743643 :   SetBlockForNode(block, node);
     215   100744190 : }
     216             : 
     217             : 
     218     6792000 : void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
     219             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     220             :   block->set_control(BasicBlock::kGoto);
     221     6792000 :   AddSuccessor(block, succ);
     222     6791975 : }
     223             : 
     224             : #if DEBUG
     225             : namespace {
     226             : 
     227             : bool IsPotentiallyThrowingCall(IrOpcode::Value opcode) {
     228             :   switch (opcode) {
     229             : #define BUILD_BLOCK_JS_CASE(Name) case IrOpcode::k##Name:
     230             :     JS_OP_LIST(BUILD_BLOCK_JS_CASE)
     231             : #undef BUILD_BLOCK_JS_CASE
     232             :     case IrOpcode::kCall:
     233             :     case IrOpcode::kCallWithCallerSavedRegisters:
     234             :       return true;
     235             :     default:
     236             :       return false;
     237             :   }
     238             : }
     239             : 
     240             : }  // namespace
     241             : #endif  // DEBUG
     242             : 
     243      306596 : void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
     244             :                        BasicBlock* exception_block) {
     245             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     246             :   DCHECK(IsPotentiallyThrowingCall(call->opcode()));
     247             :   block->set_control(BasicBlock::kCall);
     248      306596 :   AddSuccessor(block, success_block);
     249      306596 :   AddSuccessor(block, exception_block);
     250             :   SetControlInput(block, call);
     251      306596 : }
     252             : 
     253             : 
     254     3893258 : void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
     255             :                          BasicBlock* fblock) {
     256             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     257             :   DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
     258             :   block->set_control(BasicBlock::kBranch);
     259     3893258 :   AddSuccessor(block, tblock);
     260     3893317 :   AddSuccessor(block, fblock);
     261             :   SetControlInput(block, branch);
     262     3893322 : }
     263             : 
     264             : 
     265       31191 : void Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
     266             :                          size_t succ_count) {
     267             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     268             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
     269             :   block->set_control(BasicBlock::kSwitch);
     270      413527 :   for (size_t index = 0; index < succ_count; ++index) {
     271      382336 :     AddSuccessor(block, succ_blocks[index]);
     272             :   }
     273             :   SetControlInput(block, sw);
     274       31191 : }
     275             : 
     276             : 
     277      331838 : void Schedule::AddTailCall(BasicBlock* block, Node* input) {
     278             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     279             :   block->set_control(BasicBlock::kTailCall);
     280             :   SetControlInput(block, input);
     281      165919 :   if (block != end()) AddSuccessor(block, end());
     282      165919 : }
     283             : 
     284             : 
     285     4046931 : void Schedule::AddReturn(BasicBlock* block, Node* input) {
     286             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     287             :   block->set_control(BasicBlock::kReturn);
     288             :   SetControlInput(block, input);
     289     2023522 :   if (block != end()) AddSuccessor(block, end());
     290     2023507 : }
     291             : 
     292             : 
     293      198634 : void Schedule::AddDeoptimize(BasicBlock* block, Node* input) {
     294             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     295             :   block->set_control(BasicBlock::kDeoptimize);
     296             :   SetControlInput(block, input);
     297       99317 :   if (block != end()) AddSuccessor(block, end());
     298       99317 : }
     299             : 
     300             : 
     301      261146 : void Schedule::AddThrow(BasicBlock* block, Node* input) {
     302             :   DCHECK_EQ(BasicBlock::kNone, block->control());
     303             :   block->set_control(BasicBlock::kThrow);
     304             :   SetControlInput(block, input);
     305      130573 :   if (block != end()) AddSuccessor(block, end());
     306      130573 : }
     307             : 
     308             : 
     309      543058 : void Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
     310             :                             BasicBlock* tblock, BasicBlock* fblock) {
     311             :   DCHECK_NE(BasicBlock::kNone, block->control());
     312             :   DCHECK_EQ(BasicBlock::kNone, end->control());
     313             :   end->set_control(block->control());
     314             :   block->set_control(BasicBlock::kBranch);
     315      271528 :   MoveSuccessors(block, end);
     316      271529 :   AddSuccessor(block, tblock);
     317      271530 :   AddSuccessor(block, fblock);
     318      271530 :   if (block->control_input() != nullptr) {
     319             :     SetControlInput(end, block->control_input());
     320             :   }
     321             :   SetControlInput(block, branch);
     322      271530 : }
     323             : 
     324             : 
     325           2 : void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
     326             :                             BasicBlock** succ_blocks, size_t succ_count) {
     327             :   DCHECK_NE(BasicBlock::kNone, block->control());
     328             :   DCHECK_EQ(BasicBlock::kNone, end->control());
     329             :   end->set_control(block->control());
     330             :   block->set_control(BasicBlock::kSwitch);
     331           1 :   MoveSuccessors(block, end);
     332           4 :   for (size_t index = 0; index < succ_count; ++index) {
     333           3 :     AddSuccessor(block, succ_blocks[index]);
     334             :   }
     335           1 :   if (block->control_input() != nullptr) {
     336             :     SetControlInput(end, block->control_input());
     337             :   }
     338             :   SetControlInput(block, sw);
     339           1 : }
     340             : 
     341      265724 : void Schedule::EnsureCFGWellFormedness() {
     342             :   // Make a copy of all the blocks for the iteration, since adding the split
     343             :   // edges will allocate new blocks.
     344             :   BasicBlockVector all_blocks_copy(all_blocks_);
     345             : 
     346             :   // Insert missing split edge blocks.
     347     2491041 :   for (auto block : all_blocks_copy) {
     348     1636837 :     if (block->PredecessorCount() > 1) {
     349      322756 :       if (block != end_) {
     350      291103 :         EnsureSplitEdgeForm(block);
     351             :       }
     352      322756 :       if (block->deferred()) {
     353       17718 :         EnsureDeferredCodeSingleEntryPoint(block);
     354             :       }
     355             :     }
     356             :   }
     357      265724 : }
     358             : 
     359      291103 : void Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
     360             :   DCHECK(block->PredecessorCount() > 1 && block != end_);
     361     2170191 :   for (auto current_pred = block->predecessors().begin();
     362     1147206 :        current_pred != block->predecessors().end(); ++current_pred) {
     363      856103 :     BasicBlock* pred = *current_pred;
     364      856103 :     if (pred->SuccessorCount() > 1) {
     365             :       // Found a predecessor block with multiple successors.
     366      440779 :       BasicBlock* split_edge_block = NewBasicBlock();
     367             :       split_edge_block->set_control(BasicBlock::kGoto);
     368      440779 :       split_edge_block->successors().push_back(block);
     369      440779 :       split_edge_block->predecessors().push_back(pred);
     370      440779 :       split_edge_block->set_deferred(block->deferred());
     371      440779 :       *current_pred = split_edge_block;
     372             :       // Find a corresponding successor in the previous block, replace it
     373             :       // with the split edge block... but only do it once, since we only
     374             :       // replace the previous blocks in the current block one at a time.
     375     1506335 :       for (auto successor = pred->successors().begin();
     376             :            successor != pred->successors().end(); ++successor) {
     377      624777 :         if (*successor == block) {
     378      440779 :           *successor = split_edge_block;
     379      440779 :           break;
     380             :         }
     381             :       }
     382             :     }
     383             :   }
     384      291103 : }
     385             : 
     386       17718 : void Schedule::EnsureDeferredCodeSingleEntryPoint(BasicBlock* block) {
     387             :   // If a deferred block has multiple predecessors, they have to
     388             :   // all be deferred. Otherwise, we can run into a situation where a range
     389             :   // that spills only in deferred blocks inserts its spill in the block, but
     390             :   // other ranges need moves inserted by ResolveControlFlow in the predecessors,
     391             :   // which may clobber the register of this range.
     392             :   // To ensure that, when a deferred block has multiple predecessors, and some
     393             :   // are not deferred, we add a non-deferred block to collect all such edges.
     394             : 
     395             :   DCHECK(block->deferred() && block->PredecessorCount() > 1);
     396             :   bool all_deferred = true;
     397      127301 :   for (auto current_pred = block->predecessors().begin();
     398             :        current_pred != block->predecessors().end(); ++current_pred) {
     399       77873 :     BasicBlock* pred = *current_pred;
     400       77873 :     if (!pred->deferred()) {
     401             :       all_deferred = false;
     402             :       break;
     403             :     }
     404             :   }
     405             : 
     406       31710 :   if (all_deferred) return;
     407        3726 :   BasicBlock* merger = NewBasicBlock();
     408             :   merger->set_control(BasicBlock::kGoto);
     409        3726 :   merger->successors().push_back(block);
     410       41167 :   for (auto current_pred = block->predecessors().begin();
     411       33715 :        current_pred != block->predecessors().end(); ++current_pred) {
     412       29989 :     BasicBlock* pred = *current_pred;
     413       29989 :     merger->predecessors().push_back(pred);
     414       29989 :     pred->successors().clear();
     415       29989 :     pred->successors().push_back(merger);
     416             :   }
     417        3726 :   merger->set_deferred(false);
     418             :   block->predecessors().clear();
     419        3726 :   block->predecessors().push_back(merger);
     420        3726 :   MovePhis(block, merger);
     421             : }
     422             : 
     423        3726 : void Schedule::MovePhis(BasicBlock* from, BasicBlock* to) {
     424       39778 :   for (size_t i = 0; i < from->NodeCount();) {
     425       39425 :     Node* node = from->NodeAt(i);
     426       32326 :     if (node->opcode() == IrOpcode::kPhi) {
     427             :       to->AddNode(node);
     428             :       from->RemoveNode(from->begin() + i);
     429             :       DCHECK_EQ(nodeid_to_block_[node->id()], from);
     430       14198 :       nodeid_to_block_[node->id()] = to;
     431             :     } else {
     432       25227 :       ++i;
     433             :     }
     434             :   }
     435        3726 : }
     436             : 
     437      265724 : void Schedule::PropagateDeferredMark() {
     438             :   // Push forward the deferred block marks through newly inserted blocks and
     439             :   // other improperly marked blocks until a fixed point is reached.
     440             :   // TODO(danno): optimize the propagation
     441             :   bool done = false;
     442      819647 :   while (!done) {
     443             :     done = true;
     444    10886816 :     for (auto block : all_blocks_) {
     445     5869862 :       if (!block->deferred()) {
     446     3912506 :         bool deferred = block->PredecessorCount() > 0;
     447    17516276 :         for (auto pred : block->predecessors()) {
     448     9691264 :           if (!pred->deferred() && (pred->rpo_number() < block->rpo_number())) {
     449             :             deferred = false;
     450             :           }
     451             :         }
     452     3912506 :         if (deferred) {
     453             :           block->set_deferred(true);
     454             :           done = false;
     455             :         }
     456             :       }
     457             :     }
     458             :   }
     459      265724 : }
     460             : 
     461    18538498 : void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
     462             :   block->AddSuccessor(succ);
     463             :   succ->AddPredecessor(block);
     464    18538496 : }
     465             : 
     466             : 
     467      271530 : void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
     468      933939 :   for (BasicBlock* const successor : from->successors()) {
     469             :     to->AddSuccessor(successor);
     470     1515904 :     for (BasicBlock*& predecessor : successor->predecessors()) {
     471      734146 :       if (predecessor == from) predecessor = to;
     472             :     }
     473             :   }
     474             :   from->ClearSuccessors();
     475      271530 : }
     476             : 
     477             : 
     478           0 : void Schedule::SetControlInput(BasicBlock* block, Node* node) {
     479             :   block->set_control_input(node);
     480     7164944 :   SetBlockForNode(block, node);
     481           0 : }
     482             : 
     483             : 
     484   366953657 : void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
     485   550430444 :   if (node->id() >= nodeid_to_block_.size()) {
     486    17675562 :     nodeid_to_block_.resize(node->id() + 1);
     487             :   }
     488   366953740 :   nodeid_to_block_[node->id()] = block;
     489   183476870 : }
     490             : 
     491             : 
     492          12 : std::ostream& operator<<(std::ostream& os, const Schedule& s) {
     493         312 :   for (BasicBlock* block :
     494          72 :        ((s.RpoBlockCount() == 0) ? *s.all_blocks() : *s.rpo_order())) {
     495          60 :     if (block->rpo_number() == -1) {
     496           0 :       os << "--- BLOCK id:" << block->id().ToInt();
     497             :     } else {
     498          60 :       os << "--- BLOCK B" << block->rpo_number();
     499             :     }
     500          60 :     if (block->deferred()) os << " (deferred)";
     501          60 :     if (block->PredecessorCount() != 0) os << " <- ";
     502             :     bool comma = false;
     503         240 :     for (BasicBlock const* predecessor : block->predecessors()) {
     504          60 :       if (comma) os << ", ";
     505             :       comma = true;
     506          60 :       if (predecessor->rpo_number() == -1) {
     507           0 :         os << "id:" << predecessor->id().ToInt();
     508             :       } else {
     509          60 :         os << "B" << predecessor->rpo_number();
     510             :       }
     511             :     }
     512          60 :     os << " ---\n";
     513         168 :     for (Node* node : *block) {
     514          48 :       os << "  " << *node;
     515          48 :       if (NodeProperties::IsTyped(node)) {
     516             :         Type* type = NodeProperties::GetType(node);
     517           0 :         os << " : ";
     518           0 :         type->PrintTo(os);
     519             :       }
     520          48 :       os << "\n";
     521             :     }
     522             :     BasicBlock::Control control = block->control();
     523          60 :     if (control != BasicBlock::kNone) {
     524          48 :       os << "  ";
     525          48 :       if (block->control_input() != nullptr) {
     526          24 :         os << *block->control_input();
     527             :       } else {
     528          24 :         os << "Goto";
     529             :       }
     530          48 :       os << " -> ";
     531             :       comma = false;
     532         216 :       for (BasicBlock const* successor : block->successors()) {
     533          60 :         if (comma) os << ", ";
     534             :         comma = true;
     535          60 :         if (successor->rpo_number() == -1) {
     536           0 :           os << "id:" << successor->id().ToInt();
     537             :         } else {
     538          60 :           os << "B" << successor->rpo_number();
     539             :         }
     540             :       }
     541          48 :       os << "\n";
     542             :     }
     543             :   }
     544          12 :   return os;
     545             : }
     546             : 
     547             : }  // namespace compiler
     548             : }  // namespace internal
     549             : }  // namespace v8

Generated by: LCOV version 1.10