LCOV - code coverage report
Current view: top level - src/torque - instructions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 152 171 88.9 %
Date: 2019-04-17 Functions: 48 73 65.8 %

          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/instructions.h"
       6             : #include "src/torque/cfg.h"
       7             : #include "src/torque/type-oracle.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : namespace torque {
      12             : 
      13             : #define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name)        \
      14             :   const InstructionKind Name::kKind = InstructionKind::k##Name; \
      15             :   std::unique_ptr<InstructionBase> Name::Clone() const {        \
      16             :     return std::unique_ptr<InstructionBase>(new Name(*this));   \
      17             :   }                                                             \
      18             :   void Name::Assign(const InstructionBase& other) {             \
      19             :     *this = static_cast<const Name&>(other);                    \
      20             :   }
      21      288876 : TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS)
      22             : #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS
      23             : 
      24             : namespace {
      25             : void ExpectType(const Type* expected, const Type* actual) {
      26        1968 :   if (expected != actual) {
      27           0 :     ReportError("expected type ", *expected, " but found ", *actual);
      28             :   }
      29             : }
      30       23376 : void ExpectSubtype(const Type* subtype, const Type* supertype) {
      31       23376 :   if (!subtype->IsSubtypeOf(supertype)) {
      32           0 :     ReportError("type ", *subtype, " is not a subtype of ", *supertype);
      33             :   }
      34       23376 : }
      35             : }  // namespace
      36             : 
      37       21357 : void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
      38             :                                       ControlFlowGraph* cfg) const {
      39       21357 :   const Type* type = stack->Peek(slot);
      40       21357 :   if (widened_type) {
      41       21357 :     if (type->IsTopType()) {
      42             :       const TopType* top_type = TopType::cast(type);
      43           0 :       ReportError("use of " + top_type->reason());
      44             :     }
      45       21357 :     ExpectSubtype(type, *widened_type);
      46       21357 :     type = *widened_type;
      47             :   }
      48             :   stack->Push(type);
      49       21357 : }
      50             : 
      51         620 : void PokeInstruction::TypeInstruction(Stack<const Type*>* stack,
      52             :                                       ControlFlowGraph* cfg) const {
      53         620 :   const Type* type = stack->Top();
      54         620 :   if (widened_type) {
      55         620 :     ExpectSubtype(type, *widened_type);
      56         620 :     type = *widened_type;
      57             :   }
      58         620 :   stack->Poke(slot, type);
      59             :   stack->Pop();
      60         620 : }
      61             : 
      62       10124 : void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack,
      63             :                                              ControlFlowGraph* cfg) const {
      64       10124 :   stack->DeleteRange(range);
      65       10124 : }
      66             : 
      67          94 : void PushUninitializedInstruction::TypeInstruction(
      68             :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
      69          94 :   stack->Push(type);
      70          94 : }
      71             : 
      72          74 : void PushBuiltinPointerInstruction::TypeInstruction(
      73             :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
      74          74 :   stack->Push(type);
      75          74 : }
      76             : 
      77         369 : void NamespaceConstantInstruction::TypeInstruction(
      78             :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
      79         738 :   stack->PushMany(LowerType(constant->type()));
      80         369 : }
      81             : 
      82         360 : void InstructionBase::InvalidateTransientTypes(
      83             :     Stack<const Type*>* stack) const {
      84             :   auto current = stack->begin();
      85        9896 :   while (current != stack->end()) {
      86        4768 :     if ((*current)->IsTransient()) {
      87         238 :       std::stringstream stream;
      88         238 :       stream << "type " << **current
      89             :              << " is made invalid by transitioning callable invocation at "
      90         238 :              << PositionAsString(pos);
      91         357 :       *current = TypeOracle::GetTopType(stream.str(), *current);
      92             :     }
      93        4768 :     ++current;
      94             :   }
      95         360 : }
      96             : 
      97         121 : void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack,
      98             :                                                ControlFlowGraph* cfg) const {
      99             :   std::vector<const Type*> parameter_types =
     100         121 :       LowerParameterTypes(intrinsic->signature().parameter_types);
     101         224 :   for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
     102             :     const Type* arg_type = stack->Pop();
     103         103 :     const Type* parameter_type = parameter_types.back();
     104             :     parameter_types.pop_back();
     105         103 :     if (arg_type != parameter_type) {
     106             :       ReportError("parameter ", i, ": expected type ", *parameter_type,
     107           0 :                   " but found type ", *arg_type);
     108             :     }
     109             :   }
     110         121 :   if (intrinsic->IsTransitioning()) {
     111           0 :     InvalidateTransientTypes(stack);
     112             :   }
     113         242 :   stack->PushMany(LowerType(intrinsic->signature().return_type));
     114         121 : }
     115             : 
     116        4521 : void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
     117             :                                               ControlFlowGraph* cfg) const {
     118             :   std::vector<const Type*> parameter_types =
     119        4521 :       LowerParameterTypes(macro->signature().parameter_types);
     120       10930 :   for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
     121             :     const Type* arg_type = stack->Pop();
     122        6409 :     const Type* parameter_type = parameter_types.back();
     123             :     parameter_types.pop_back();
     124        6409 :     if (arg_type != parameter_type) {
     125             :       ReportError("parameter ", i, ": expected type ", *parameter_type,
     126           0 :                   " but found type ", *arg_type);
     127             :     }
     128             :   }
     129             : 
     130        4521 :   if (macro->IsTransitioning()) {
     131         194 :     InvalidateTransientTypes(stack);
     132             :   }
     133             : 
     134        4521 :   if (catch_block) {
     135             :     Stack<const Type*> catch_stack = *stack;
     136           8 :     catch_stack.Push(TypeOracle::GetObjectType());
     137           8 :     (*catch_block)->SetInputTypes(catch_stack);
     138             :   }
     139             : 
     140        9042 :   stack->PushMany(LowerType(macro->signature().return_type));
     141        4521 : }
     142             : 
     143         619 : void CallCsaMacroAndBranchInstruction::TypeInstruction(
     144             :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
     145             :   std::vector<const Type*> parameter_types =
     146         619 :       LowerParameterTypes(macro->signature().parameter_types);
     147        1745 :   for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
     148             :     const Type* arg_type = stack->Pop();
     149        1126 :     const Type* parameter_type = parameter_types.back();
     150             :     parameter_types.pop_back();
     151        1126 :     if (arg_type != parameter_type) {
     152             :       ReportError("parameter ", i, ": expected type ", *parameter_type,
     153           0 :                   " but found type ", *arg_type);
     154             :     }
     155             :   }
     156             : 
     157        1238 :   if (label_blocks.size() != macro->signature().labels.size()) {
     158           0 :     ReportError("wrong number of labels");
     159             :   }
     160        1823 :   for (size_t i = 0; i < label_blocks.size(); ++i) {
     161             :     Stack<const Type*> continuation_stack = *stack;
     162             :     continuation_stack.PushMany(
     163        1806 :         LowerParameterTypes(macro->signature().labels[i].types));
     164         602 :     label_blocks[i]->SetInputTypes(std::move(continuation_stack));
     165             :   }
     166             : 
     167         619 :   if (macro->IsTransitioning()) {
     168          19 :     InvalidateTransientTypes(stack);
     169             :   }
     170             : 
     171         619 :   if (catch_block) {
     172             :     Stack<const Type*> catch_stack = *stack;
     173           4 :     catch_stack.Push(TypeOracle::GetObjectType());
     174           4 :     (*catch_block)->SetInputTypes(catch_stack);
     175             :   }
     176             : 
     177         619 :   if (macro->signature().return_type != TypeOracle::GetNeverType()) {
     178             :     Stack<const Type*> return_stack = *stack;
     179         868 :     return_stack.PushMany(LowerType(macro->signature().return_type));
     180         434 :     if (return_continuation == base::nullopt) {
     181           0 :       ReportError("missing return continuation.");
     182             :     }
     183         434 :     (*return_continuation)->SetInputTypes(return_stack);
     184             :   } else {
     185         185 :     if (return_continuation != base::nullopt) {
     186           0 :       ReportError("unreachable return continuation.");
     187             :     }
     188             :   }
     189         619 : }
     190             : 
     191         144 : void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack,
     192             :                                              ControlFlowGraph* cfg) const {
     193         144 :   std::vector<const Type*> argument_types = stack->PopMany(argc);
     194         144 :   if (argument_types !=
     195         288 :       LowerParameterTypes(builtin->signature().parameter_types)) {
     196           0 :     ReportError("wrong argument types");
     197             :   }
     198         144 :   if (builtin->IsTransitioning()) {
     199         111 :     InvalidateTransientTypes(stack);
     200             :   }
     201             : 
     202         144 :   if (catch_block) {
     203             :     Stack<const Type*> catch_stack = *stack;
     204           1 :     catch_stack.Push(TypeOracle::GetObjectType());
     205           1 :     (*catch_block)->SetInputTypes(catch_stack);
     206             :   }
     207             : 
     208         288 :   stack->PushMany(LowerType(builtin->signature().return_type));
     209         144 : }
     210             : 
     211          31 : void CallBuiltinPointerInstruction::TypeInstruction(
     212             :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
     213          31 :   std::vector<const Type*> argument_types = stack->PopMany(argc);
     214             :   const BuiltinPointerType* f = BuiltinPointerType::DynamicCast(stack->Pop());
     215          31 :   if (!f) ReportError("expected function pointer type");
     216          62 :   if (argument_types != LowerParameterTypes(f->parameter_types())) {
     217           0 :     ReportError("wrong argument types");
     218             :   }
     219             :   // TODO(tebbi): Only invalidate transient types if the function pointer type
     220             :   // is transitioning.
     221          31 :   InvalidateTransientTypes(stack);
     222          62 :   stack->PushMany(LowerType(f->return_type()));
     223          31 : }
     224             : 
     225          27 : void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack,
     226             :                                              ControlFlowGraph* cfg) const {
     227          27 :   std::vector<const Type*> argument_types = stack->PopMany(argc);
     228          27 :   if (argument_types !=
     229          54 :       LowerParameterTypes(runtime_function->signature().parameter_types,
     230          27 :                           argc)) {
     231           0 :     ReportError("wrong argument types");
     232             :   }
     233          27 :   if (runtime_function->IsTransitioning()) {
     234           5 :     InvalidateTransientTypes(stack);
     235             :   }
     236             : 
     237          27 :   if (catch_block) {
     238             :     Stack<const Type*> catch_stack = *stack;
     239           0 :     catch_stack.Push(TypeOracle::GetObjectType());
     240           0 :     (*catch_block)->SetInputTypes(catch_stack);
     241             :   }
     242             : 
     243          27 :   const Type* return_type = runtime_function->signature().return_type;
     244          27 :   if (return_type != TypeOracle::GetNeverType()) {
     245          30 :     stack->PushMany(LowerType(return_type));
     246             :   }
     247          27 : }
     248             : 
     249         905 : void BranchInstruction::TypeInstruction(Stack<const Type*>* stack,
     250             :                                         ControlFlowGraph* cfg) const {
     251             :   const Type* condition_type = stack->Pop();
     252         905 :   if (condition_type != TypeOracle::GetBoolType()) {
     253           0 :     ReportError("condition has to have type bool");
     254             :   }
     255         905 :   if_true->SetInputTypes(*stack);
     256         905 :   if_false->SetInputTypes(*stack);
     257         905 : }
     258             : 
     259          53 : void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack,
     260             :                                                  ControlFlowGraph* cfg) const {
     261          53 :   if_true->SetInputTypes(*stack);
     262          53 :   if_false->SetInputTypes(*stack);
     263          53 : }
     264             : 
     265        4683 : void GotoInstruction::TypeInstruction(Stack<const Type*>* stack,
     266             :                                       ControlFlowGraph* cfg) const {
     267        4683 :   destination->SetInputTypes(*stack);
     268        4683 : }
     269             : 
     270         136 : void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack,
     271             :                                               ControlFlowGraph* cfg) const {
     272         136 :   if (variable_names.size() != stack->Size()) {
     273           0 :     ReportError("goto external label with wrong parameter count.");
     274             :   }
     275         136 : }
     276             : 
     277         243 : void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack,
     278             :                                         ControlFlowGraph* cfg) const {
     279         243 :   cfg->SetReturnType(stack->Pop());
     280         243 : }
     281             : 
     282           0 : void PrintConstantStringInstruction::TypeInstruction(
     283           0 :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {}
     284             : 
     285         238 : void AbortInstruction::TypeInstruction(Stack<const Type*>* stack,
     286         238 :                                        ControlFlowGraph* cfg) const {}
     287             : 
     288          42 : void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
     289             :                                             ControlFlowGraph* cfg) const {
     290          84 :   stack->Poke(stack->AboveTop() - 1, destination_type);
     291          42 : }
     292             : 
     293         979 : void CreateFieldReferenceInstruction::TypeInstruction(
     294             :     Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
     295        1958 :   ExpectSubtype(stack->Pop(), class_type);
     296         979 :   stack->Push(TypeOracle::GetHeapObjectType());
     297         979 :   stack->Push(TypeOracle::GetIntPtrType());
     298         979 : }
     299             : 
     300         564 : void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
     301             :                                                ControlFlowGraph* cfg) const {
     302         564 :   ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
     303         564 :   ExpectType(TypeOracle::GetHeapObjectType(), stack->Pop());
     304             :   DCHECK_EQ(std::vector<const Type*>{type}, LowerType(type));
     305         564 :   stack->Push(type);
     306         564 : }
     307             : 
     308         420 : void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
     309             :                                                 ControlFlowGraph* cfg) const {
     310         840 :   ExpectSubtype(stack->Pop(), type);
     311         420 :   ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
     312         420 :   ExpectType(TypeOracle::GetHeapObjectType(), stack->Pop());
     313         420 : }
     314             : 
     315          47 : bool CallRuntimeInstruction::IsBlockTerminator() const {
     316          94 :   return is_tailcall || runtime_function->signature().return_type ==
     317          94 :                             TypeOracle::GetNeverType();
     318             : }
     319             : 
     320             : }  // namespace torque
     321             : }  // namespace internal
     322       59456 : }  // namespace v8

Generated by: LCOV version 1.10