LCOV - code coverage report
Current view: top level - src/torque - instructions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 146 169 86.4 %
Date: 2019-01-20 Functions: 46 70 65.7 %

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

Generated by: LCOV version 1.10