LCOV - code coverage report
Current view: top level - src/torque - instructions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 145 168 86.3 %
Date: 2019-03-21 Functions: 45 69 65.2 %

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

Generated by: LCOV version 1.10