LCOV - code coverage report
Current view: top level - src/torque - cfg.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 45 73 61.6 %
Date: 2019-01-20 Functions: 11 15 73.3 %

          Line data    Source code
       1             : // Copyright 2018 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/torque/cfg.h"
       6             : 
       7             : #include "src/torque/type-oracle.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : namespace torque {
      12             : 
      13        4478 : void Block::SetInputTypes(const Stack<const Type*>& input_types) {
      14        4478 :   if (!input_types_) {
      15             :     input_types_ = input_types;
      16             :     return;
      17        2688 :   } else if (*input_types_ == input_types) {
      18             :     return;
      19             :   }
      20             : 
      21             :   DCHECK_EQ(input_types.Size(), input_types_->Size());
      22             :   Stack<const Type*> merged_types;
      23             :   bool widened = false;
      24             :   auto c2_iterator = input_types.begin();
      25         497 :   for (const Type* c1 : *input_types_) {
      26         463 :     const Type* merged_type = TypeOracle::GetUnionType(c1, *c2_iterator++);
      27         463 :     if (!merged_type->IsSubtypeOf(c1)) {
      28             :       widened = true;
      29             :     }
      30             :     merged_types.Push(merged_type);
      31             :   }
      32          34 :   if (merged_types.Size() == input_types_->Size()) {
      33          34 :     if (widened) {
      34             :       input_types_ = merged_types;
      35          11 :       Retype();
      36             :     }
      37             :     return;
      38             :   }
      39             : 
      40           0 :   std::stringstream error;
      41           0 :   error << "incompatible types at branch:\n";
      42           0 :   for (intptr_t i = std::max(input_types_->Size(), input_types.Size()) - 1;
      43             :        i >= 0; --i) {
      44             :     base::Optional<const Type*> left;
      45             :     base::Optional<const Type*> right;
      46           0 :     if (static_cast<size_t>(i) < input_types.Size()) {
      47             :       left = input_types.Peek(BottomOffset{static_cast<size_t>(i)});
      48             :     }
      49           0 :     if (static_cast<size_t>(i) < input_types_->Size()) {
      50             :       right = input_types_->Peek(BottomOffset{static_cast<size_t>(i)});
      51             :     }
      52           0 :     if (left && right && *left == *right) {
      53           0 :       error << **left << "\n";
      54             :     } else {
      55           0 :       if (left) {
      56           0 :         error << **left;
      57             :       } else {
      58           0 :         error << "/*missing*/";
      59             :       }
      60           0 :       error << "   =>   ";
      61           0 :       if (right) {
      62           0 :         error << **right;
      63             :       } else {
      64           0 :         error << "/*missing*/";
      65             :       }
      66           0 :       error << "\n";
      67             :     }
      68             :   }
      69           0 :   ReportError(error.str());
      70             : }
      71             : 
      72        3776 : void CfgAssembler::Bind(Block* block) {
      73             :   DCHECK(current_block_->IsComplete());
      74             :   DCHECK(block->instructions().empty());
      75             :   DCHECK(block->HasInputTypes());
      76        3776 :   current_block_ = block;
      77             :   current_stack_ = block->InputTypes();
      78             :   cfg_.PlaceBlock(block);
      79        3776 : }
      80             : 
      81        1386 : void CfgAssembler::Goto(Block* block) {
      82        1386 :   if (block->HasInputTypes()) {
      83         499 :     DropTo(block->InputTypes().AboveTop());
      84             :   }
      85        2772 :   Emit(GotoInstruction{block});
      86        1386 : }
      87             : 
      88        1030 : StackRange CfgAssembler::Goto(Block* block, size_t preserved_slots) {
      89             :   DCHECK(block->HasInputTypes());
      90             :   DCHECK_GE(CurrentStack().Size(), block->InputTypes().Size());
      91             :   Emit(DeleteRangeInstruction{
      92             :       StackRange{block->InputTypes().AboveTop() - preserved_slots,
      93        3090 :                  CurrentStack().AboveTop() - preserved_slots}});
      94             :   StackRange preserved_slot_range = TopRange(preserved_slots);
      95        2060 :   Emit(GotoInstruction{block});
      96        1030 :   return preserved_slot_range;
      97             : }
      98             : 
      99         577 : void CfgAssembler::Branch(Block* if_true, Block* if_false) {
     100        1154 :   Emit(BranchInstruction{if_true, if_false});
     101         577 : }
     102             : 
     103             : // Delete the specified range of slots, moving upper slots to fill the gap.
     104       40828 : void CfgAssembler::DeleteRange(StackRange range) {
     105             :   DCHECK_LE(range.end(), current_stack_.AboveTop());
     106       81656 :   if (range.Size() == 0) return;
     107       10400 :   Emit(DeleteRangeInstruction{range});
     108             : }
     109             : 
     110       22960 : void CfgAssembler::DropTo(BottomOffset new_level) {
     111       22960 :   DeleteRange(StackRange{new_level, CurrentStack().AboveTop()});
     112       22960 : }
     113             : 
     114       12166 : StackRange CfgAssembler::Peek(StackRange range,
     115       24589 :                               base::Optional<const Type*> type) {
     116             :   std::vector<const Type*> lowered_types;
     117       12166 :   if (type) {
     118       24332 :     lowered_types = LowerType(*type);
     119             :     DCHECK_EQ(lowered_types.size(), range.Size());
     120             :   }
     121       37012 :   for (size_t i = 0; i < range.Size(); ++i) {
     122             :     Emit(PeekInstruction{
     123             :         range.begin() + i,
     124       49692 :         type ? lowered_types[i] : base::Optional<const Type*>{}});
     125             :   }
     126       12166 :   return TopRange(range.Size());
     127             : }
     128             : 
     129         440 : void CfgAssembler::Poke(StackRange destination, StackRange origin,
     130         907 :                         base::Optional<const Type*> type) {
     131             :   DCHECK_EQ(destination.Size(), origin.Size());
     132             :   DCHECK_LE(destination.end(), origin.begin());
     133             :   DCHECK_EQ(origin.end(), CurrentStack().AboveTop());
     134             :   std::vector<const Type*> lowered_types;
     135         440 :   if (type) {
     136         880 :     lowered_types = LowerType(*type);
     137             :     DCHECK_EQ(lowered_types.size(), origin.Size());
     138             :   }
     139         907 :   for (intptr_t i = origin.Size() - 1; i >= 0; --i) {
     140             :     Emit(PokeInstruction{
     141             :         destination.begin() + i,
     142        2335 :         type ? lowered_types[i] : base::Optional<const Type*>{}});
     143             :   }
     144         440 : }
     145             : 
     146           0 : void CfgAssembler::Print(std::string s) {
     147           0 :   Emit(PrintConstantStringInstruction{std::move(s)});
     148           0 : }
     149             : 
     150           0 : void CfgAssembler::AssertionFailure(std::string message) {
     151             :   Emit(AbortInstruction{AbortInstruction::Kind::kAssertionFailure,
     152           0 :                         std::move(message)});
     153           0 : }
     154             : 
     155           0 : void CfgAssembler::Unreachable() {
     156           0 :   Emit(AbortInstruction{AbortInstruction::Kind::kUnreachable});
     157           0 : }
     158             : 
     159           0 : void CfgAssembler::DebugBreak() {
     160           0 :   Emit(AbortInstruction{AbortInstruction::Kind::kDebugBreak});
     161           0 : }
     162             : 
     163             : }  // namespace torque
     164             : }  // namespace internal
     165        9078 : }  // namespace v8

Generated by: LCOV version 1.10