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

Generated by: LCOV version 1.10