LCOV - code coverage report
Current view: top level - src/compiler - linkage.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 114 133 85.7 %
Date: 2019-01-20 Functions: 20 21 95.2 %

          Line data    Source code
       1             : // Copyright 2014 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/compiler/linkage.h"
       6             : 
       7             : #include "src/assembler-inl.h"
       8             : #include "src/compiler/common-operator.h"
       9             : #include "src/compiler/frame.h"
      10             : #include "src/compiler/node.h"
      11             : #include "src/compiler/osr.h"
      12             : #include "src/compiler/pipeline.h"
      13             : #include "src/macro-assembler.h"
      14             : #include "src/optimized-compilation-info.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : namespace compiler {
      19             : 
      20             : namespace {
      21             : 
      22             : inline LinkageLocation regloc(Register reg, MachineType type) {
      23             :   return LinkageLocation::ForRegister(reg.code(), type);
      24             : }
      25             : 
      26             : }  // namespace
      27             : 
      28             : 
      29          56 : std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) {
      30          56 :   switch (k) {
      31             :     case CallDescriptor::kCallCodeObject:
      32          47 :       os << "Code";
      33          47 :       break;
      34             :     case CallDescriptor::kCallJSFunction:
      35           0 :       os << "JS";
      36           0 :       break;
      37             :     case CallDescriptor::kCallAddress:
      38           0 :       os << "Addr";
      39           0 :       break;
      40             :     case CallDescriptor::kCallWasmFunction:
      41           9 :       os << "WasmFunction";
      42           9 :       break;
      43             :     case CallDescriptor::kCallWasmImportWrapper:
      44           0 :       os << "WasmImportWrapper";
      45           0 :       break;
      46             :     case CallDescriptor::kCallBuiltinPointer:
      47           0 :       os << "BuiltinPointer";
      48           0 :       break;
      49             :   }
      50          56 :   return os;
      51             : }
      52             : 
      53             : 
      54         224 : std::ostream& operator<<(std::ostream& os, const CallDescriptor& d) {
      55             :   // TODO(svenpanne) Output properties etc. and be less cryptic.
      56         112 :   return os << d.kind() << ":" << d.debug_name() << ":r" << d.ReturnCount()
      57         168 :             << "s" << d.StackParameterCount() << "i" << d.InputCount() << "f"
      58          56 :             << d.FrameStateCount();
      59             : }
      60             : 
      61       48160 : MachineSignature* CallDescriptor::GetMachineSignature(Zone* zone) const {
      62             :   size_t param_count = ParameterCount();
      63             :   size_t return_count = ReturnCount();
      64       12040 :   MachineType* types = zone->NewArray<MachineType>(param_count + return_count);
      65             :   int current = 0;
      66       24080 :   for (size_t i = 0; i < return_count; ++i) {
      67       24080 :     types[current++] = GetReturnType(i);
      68             :   }
      69       24080 :   for (size_t i = 0; i < param_count; ++i) {
      70       48160 :     types[current++] = GetParameterType(i);
      71             :   }
      72       12040 :   return new (zone) MachineSignature(return_count, param_count, types);
      73             : }
      74             : 
      75          13 : bool CallDescriptor::HasSameReturnLocationsAs(
      76          26 :     const CallDescriptor* other) const {
      77          13 :   if (ReturnCount() != other->ReturnCount()) return false;
      78          11 :   for (size_t i = 0; i < ReturnCount(); ++i) {
      79          12 :     if (GetReturnLocation(i) != other->GetReturnLocation(i)) return false;
      80             :   }
      81             :   return true;
      82             : }
      83             : 
      84     2667499 : int CallDescriptor::GetFirstUnusedStackSlot() const {
      85             :   int slots_above_sp = 0;
      86     4625378 :   for (size_t i = 0; i < InputCount(); ++i) {
      87     1957879 :     LinkageLocation operand = GetInputLocation(i);
      88     1957879 :     if (!operand.IsRegister()) {
      89             :       int new_candidate =
      90      122513 :           -operand.GetLocation() + operand.GetSizeInPointers() - 1;
      91      122513 :       if (new_candidate > slots_above_sp) {
      92             :         slots_above_sp = new_candidate;
      93             :       }
      94             :     }
      95             :   }
      96      354810 :   return slots_above_sp;
      97             : }
      98             : 
      99      118274 : int CallDescriptor::GetStackParameterDelta(
     100             :     CallDescriptor const* tail_caller) const {
     101      118274 :   int callee_slots_above_sp = GetFirstUnusedStackSlot();
     102      118274 :   int tail_caller_slots_above_sp = tail_caller->GetFirstUnusedStackSlot();
     103      118274 :   int stack_param_delta = callee_slots_above_sp - tail_caller_slots_above_sp;
     104             :   if (kPadArguments) {
     105             :     // Adjust stack delta when it is odd.
     106             :     if (stack_param_delta % 2 != 0) {
     107             :       if (callee_slots_above_sp % 2 != 0) {
     108             :         // The delta is odd due to the callee - we will need to add one slot
     109             :         // of padding.
     110             :         ++stack_param_delta;
     111             :       } else {
     112             :         // The delta is odd because of the caller. We already have one slot of
     113             :         // padding that we can reuse for arguments, so we will need one fewer
     114             :         // slot.
     115             :         --stack_param_delta;
     116             :       }
     117             :     }
     118             :   }
     119      118274 :   return stack_param_delta;
     120             : }
     121             : 
     122          13 : bool CallDescriptor::CanTailCall(const Node* node) const {
     123          13 :   return HasSameReturnLocationsAs(CallDescriptorOf(node->op()));
     124             : }
     125             : 
     126     5910225 : int CallDescriptor::CalculateFixedFrameSize() const {
     127     5910225 :   switch (kind_) {
     128             :     case kCallJSFunction:
     129             :       return PushArgumentCount()
     130             :                  ? OptimizedBuiltinFrameConstants::kFixedSlotCount
     131     1305751 :                  : StandardFrameConstants::kFixedSlotCount;
     132             :     case kCallAddress:
     133             :       return CommonFrameConstants::kFixedSlotCountAboveFp +
     134             :              CommonFrameConstants::kCPSlotCount;
     135             :     case kCallCodeObject:
     136             :     case kCallBuiltinPointer:
     137      205516 :       return TypedFrameConstants::kFixedSlotCount;
     138             :     case kCallWasmFunction:
     139             :     case kCallWasmImportWrapper:
     140     2138755 :       return WasmCompiledFrameConstants::kFixedSlotCount;
     141             :   }
     142           0 :   UNREACHABLE();
     143             : }
     144             : 
     145      456167 : CallDescriptor* Linkage::ComputeIncoming(Zone* zone,
     146             :                                          OptimizedCompilationInfo* info) {
     147             :   DCHECK(!info->IsNotOptimizedFunctionOrWasmFunction());
     148      456167 :   if (!info->closure().is_null()) {
     149             :     // If we are compiling a JS function, use a JS call descriptor,
     150             :     // plus the receiver.
     151      456173 :     SharedFunctionInfo shared = info->closure()->shared();
     152             :     return GetJSCallDescriptor(zone, info->is_osr(),
     153             :                                1 + shared->internal_formal_parameter_count(),
     154      912340 :                                CallDescriptor::kCanUseRoots);
     155             :   }
     156             :   return nullptr;  // TODO(titzer): ?
     157             : }
     158             : 
     159             : 
     160             : // static
     161    11951559 : bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
     162    11951559 :   switch (function) {
     163             :     // Most runtime functions need a FrameState. A few chosen ones that we know
     164             :     // not to call into arbitrary JavaScript, not to throw, and not to lazily
     165             :     // deoptimize are whitelisted here and can be called without a FrameState.
     166             :     case Runtime::kAbort:
     167             :     case Runtime::kAllocateInTargetSpace:
     168             :     case Runtime::kCreateIterResultObject:
     169             :     case Runtime::kIncBlockCounter:
     170             :     case Runtime::kIsFunction:
     171             :     case Runtime::kNewClosure:
     172             :     case Runtime::kNewClosure_Tenured:
     173             :     case Runtime::kNewFunctionContext:
     174             :     case Runtime::kPushBlockContext:
     175             :     case Runtime::kPushCatchContext:
     176             :     case Runtime::kReThrow:
     177             :     case Runtime::kStringEqual:
     178             :     case Runtime::kStringLessThan:
     179             :     case Runtime::kStringLessThanOrEqual:
     180             :     case Runtime::kStringGreaterThan:
     181             :     case Runtime::kStringGreaterThanOrEqual:
     182             :     case Runtime::kToFastProperties:  // TODO(conradw): Is it safe?
     183             :     case Runtime::kTraceEnter:
     184             :     case Runtime::kTraceExit:
     185             :       return false;
     186             : 
     187             :     // Some inline intrinsics are also safe to call without a FrameState.
     188             :     case Runtime::kInlineCreateIterResultObject:
     189             :     case Runtime::kInlineGeneratorClose:
     190             :     case Runtime::kInlineGeneratorGetResumeMode:
     191             :     case Runtime::kInlineCreateJSGeneratorObject:
     192             :     case Runtime::kInlineIsArray:
     193             :     case Runtime::kInlineIsJSReceiver:
     194             :     case Runtime::kInlineIsRegExp:
     195             :     case Runtime::kInlineIsSmi:
     196             :     case Runtime::kInlineIsTypedArray:
     197             :       return false;
     198             : 
     199             :     default:
     200             :       break;
     201             :   }
     202             : 
     203             :   // For safety, default to needing a FrameState unless whitelisted.
     204    11346855 :   return true;
     205             : }
     206             : 
     207             : 
     208           0 : bool CallDescriptor::UsesOnlyRegisters() const {
     209           0 :   for (size_t i = 0; i < InputCount(); ++i) {
     210           0 :     if (!GetInputLocation(i).IsRegister()) return false;
     211             :   }
     212           0 :   for (size_t i = 0; i < ReturnCount(); ++i) {
     213           0 :     if (!GetReturnLocation(i).IsRegister()) return false;
     214             :   }
     215             :   return true;
     216             : }
     217             : 
     218             : 
     219     1013630 : CallDescriptor* Linkage::GetRuntimeCallDescriptor(
     220             :     Zone* zone, Runtime::FunctionId function_id, int js_parameter_count,
     221             :     Operator::Properties properties, CallDescriptor::Flags flags) {
     222     1013630 :   const Runtime::Function* function = Runtime::FunctionForId(function_id);
     223     1013637 :   const int return_count = function->result_size;
     224     1013637 :   const char* debug_name = function->name;
     225             : 
     226     1013637 :   if (!Linkage::NeedsFrameStateInput(function_id)) {
     227             :     flags = static_cast<CallDescriptor::Flags>(
     228             :         flags & ~CallDescriptor::kNeedsFrameState);
     229             :   }
     230             : 
     231             :   return GetCEntryStubCallDescriptor(zone, return_count, js_parameter_count,
     232     1013644 :                                      debug_name, properties, flags);
     233             : }
     234             : 
     235     1017159 : CallDescriptor* Linkage::GetCEntryStubCallDescriptor(
     236             :     Zone* zone, int return_count, int js_parameter_count,
     237             :     const char* debug_name, Operator::Properties properties,
     238             :     CallDescriptor::Flags flags) {
     239             :   const size_t function_count = 1;
     240             :   const size_t num_args_count = 1;
     241             :   const size_t context_count = 1;
     242             :   const size_t parameter_count = function_count +
     243             :                                  static_cast<size_t>(js_parameter_count) +
     244     1017159 :                                  num_args_count + context_count;
     245             : 
     246             :   LocationSignature::Builder locations(zone, static_cast<size_t>(return_count),
     247     1017159 :                                        static_cast<size_t>(parameter_count));
     248             : 
     249             :   // Add returns.
     250     1017153 :   if (locations.return_count_ > 0) {
     251             :     locations.AddReturn(regloc(kReturnRegister0, MachineType::AnyTagged()));
     252             :   }
     253     1017153 :   if (locations.return_count_ > 1) {
     254        2112 :     locations.AddReturn(regloc(kReturnRegister1, MachineType::AnyTagged()));
     255             :   }
     256     1017153 :   if (locations.return_count_ > 2) {
     257           0 :     locations.AddReturn(regloc(kReturnRegister2, MachineType::AnyTagged()));
     258             :   }
     259             : 
     260             :   // All parameters to the runtime call go on the stack.
     261      930786 :   for (int i = 0; i < js_parameter_count; i++) {
     262             :     locations.AddParam(LinkageLocation::ForCallerFrameSlot(
     263      930786 :         i - js_parameter_count, MachineType::AnyTagged()));
     264             :   }
     265             :   // Add runtime function itself.
     266             :   locations.AddParam(
     267             :       regloc(kRuntimeCallFunctionRegister, MachineType::Pointer()));
     268             : 
     269             :   // Add runtime call argument count.
     270             :   locations.AddParam(
     271             :       regloc(kRuntimeCallArgCountRegister, MachineType::Int32()));
     272             : 
     273             :   // Add context.
     274             :   locations.AddParam(regloc(kContextRegister, MachineType::AnyTagged()));
     275             : 
     276             :   // The target for runtime calls is a code object.
     277             :   MachineType target_type = MachineType::AnyTagged();
     278             :   LinkageLocation target_loc =
     279             :       LinkageLocation::ForAnyRegister(MachineType::AnyTagged());
     280             :   return new (zone) CallDescriptor(     // --
     281             :       CallDescriptor::kCallCodeObject,  // kind
     282             :       target_type,                      // target MachineType
     283             :       target_loc,                       // target location
     284             :       locations.Build(),                // location_sig
     285             :       js_parameter_count,               // stack_parameter_count
     286             :       properties,                       // properties
     287             :       kNoCalleeSaved,                   // callee-saved
     288             :       kNoCalleeSaved,                   // callee-saved fp
     289             :       flags,                            // flags
     290     2034321 :       debug_name);                      // debug name
     291             : }
     292             : 
     293      734254 : CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
     294             :                                              int js_parameter_count,
     295             :                                              CallDescriptor::Flags flags) {
     296             :   const size_t return_count = 1;
     297             :   const size_t context_count = 1;
     298             :   const size_t new_target_count = 1;
     299             :   const size_t num_args_count = 1;
     300             :   const size_t parameter_count =
     301      734254 :       js_parameter_count + new_target_count + num_args_count + context_count;
     302             : 
     303             :   LocationSignature::Builder locations(zone, return_count, parameter_count);
     304             : 
     305             :   // All JS calls have exactly one return value.
     306             :   locations.AddReturn(regloc(kReturnRegister0, MachineType::AnyTagged()));
     307             : 
     308             :   // All parameters to JS calls go on the stack.
     309     2814076 :   for (int i = 0; i < js_parameter_count; i++) {
     310     2079807 :     int spill_slot_index = i - js_parameter_count;
     311             :     locations.AddParam(LinkageLocation::ForCallerFrameSlot(
     312             :         spill_slot_index, MachineType::AnyTagged()));
     313             :   }
     314             : 
     315             :   // Add JavaScript call new target value.
     316             :   locations.AddParam(
     317             :       regloc(kJavaScriptCallNewTargetRegister, MachineType::AnyTagged()));
     318             : 
     319             :   // Add JavaScript call argument count.
     320             :   locations.AddParam(
     321             :       regloc(kJavaScriptCallArgCountRegister, MachineType::Int32()));
     322             : 
     323             :   // Add context.
     324             :   locations.AddParam(regloc(kContextRegister, MachineType::AnyTagged()));
     325             : 
     326             :   // The target for JS function calls is the JSFunction object.
     327             :   MachineType target_type = MachineType::AnyTagged();
     328             :   // When entering into an OSR function from unoptimized code the JSFunction
     329             :   // is not in a register, but it is on the stack in the marker spill slot.
     330             :   LinkageLocation target_loc =
     331             :       is_osr ? LinkageLocation::ForSavedCallerFunction()
     332      734269 :              : regloc(kJSFunctionRegister, MachineType::AnyTagged());
     333             :   return new (zone) CallDescriptor(     // --
     334             :       CallDescriptor::kCallJSFunction,  // kind
     335             :       target_type,                      // target MachineType
     336             :       target_loc,                       // target location
     337             :       locations.Build(),                // location_sig
     338             :       js_parameter_count,               // stack_parameter_count
     339             :       Operator::kNoProperties,          // properties
     340             :       kNoCalleeSaved,                   // callee-saved
     341             :       kNoCalleeSaved,                   // callee-saved fp
     342             :       flags,                            // flags
     343     1468542 :       "js-call");
     344             : }
     345             : 
     346             : // TODO(turbofan): cache call descriptors for code stub calls.
     347             : // TODO(jgruber): Clean up stack parameter count handling. The descriptor
     348             : // already knows the formal stack parameter count and ideally only additional
     349             : // stack parameters should be passed into this method. All call-sites should
     350             : // be audited for correctness (e.g. many used to assume a stack parameter count
     351             : // of 0).
     352     2713027 : CallDescriptor* Linkage::GetStubCallDescriptor(
     353             :     Zone* zone, const CallInterfaceDescriptor& descriptor,
     354             :     int stack_parameter_count, CallDescriptor::Flags flags,
     355             :     Operator::Properties properties, StubCallMode stub_mode) {
     356             :   const int register_parameter_count = descriptor.GetRegisterParameterCount();
     357             :   const int js_parameter_count =
     358     2713027 :       register_parameter_count + stack_parameter_count;
     359     2713027 :   const int context_count = descriptor.HasContextParameter() ? 1 : 0;
     360             :   const size_t parameter_count =
     361     2713027 :       static_cast<size_t>(js_parameter_count + context_count);
     362             : 
     363             :   DCHECK_GE(stack_parameter_count, descriptor.GetStackParameterCount());
     364             : 
     365     2713027 :   size_t return_count = descriptor.GetReturnCount();
     366             :   LocationSignature::Builder locations(zone, return_count, parameter_count);
     367             : 
     368             :   // Add returns.
     369     2713050 :   if (locations.return_count_ > 0) {
     370             :     locations.AddReturn(regloc(kReturnRegister0, descriptor.GetReturnType(0)));
     371             :   }
     372     2713050 :   if (locations.return_count_ > 1) {
     373         171 :     locations.AddReturn(regloc(kReturnRegister1, descriptor.GetReturnType(1)));
     374             :   }
     375     2713050 :   if (locations.return_count_ > 2) {
     376           0 :     locations.AddReturn(regloc(kReturnRegister2, descriptor.GetReturnType(2)));
     377             :   }
     378             : 
     379             :   // Add parameters in registers and on the stack.
     380     7512411 :   for (int i = 0; i < js_parameter_count; i++) {
     381     7512411 :     if (i < register_parameter_count) {
     382             :       // The first parameters go in registers.
     383             :       Register reg = descriptor.GetRegisterParameter(i);
     384             :       MachineType type = descriptor.GetParameterType(i);
     385             :       locations.AddParam(regloc(reg, type));
     386             :     } else {
     387             :       // The rest of the parameters go on the stack.
     388     1283288 :       int stack_slot = i - register_parameter_count - stack_parameter_count;
     389             :       locations.AddParam(LinkageLocation::ForCallerFrameSlot(
     390             :           stack_slot, MachineType::AnyTagged()));
     391             :     }
     392             :   }
     393             :   // Add context.
     394     2713050 :   if (context_count) {
     395             :     locations.AddParam(regloc(kContextRegister, MachineType::AnyTagged()));
     396             :   }
     397             : 
     398             :   // The target for stub calls depends on the requested mode.
     399             :   CallDescriptor::Kind kind;
     400             :   MachineType target_type;
     401     2713050 :   switch (stub_mode) {
     402             :     case StubCallMode::kCallCodeObject:
     403             :       kind = CallDescriptor::kCallCodeObject;
     404             :       target_type = MachineType::AnyTagged();
     405     2680544 :       break;
     406             :     case StubCallMode::kCallWasmRuntimeStub:
     407             :       kind = CallDescriptor::kCallWasmFunction;
     408             :       target_type = MachineType::Pointer();
     409       26599 :       break;
     410             :     case StubCallMode::kCallBuiltinPointer:
     411             :       kind = CallDescriptor::kCallBuiltinPointer;
     412             :       target_type = MachineType::AnyTagged();
     413        5910 :       break;
     414             :   }
     415             : 
     416             :   LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
     417             :   return new (zone) CallDescriptor(          // --
     418             :       kind,                                  // kind
     419             :       target_type,                           // target MachineType
     420             :       target_loc,                            // target location
     421             :       locations.Build(),                     // location_sig
     422             :       stack_parameter_count,                 // stack_parameter_count
     423             :       properties,                            // properties
     424             :       kNoCalleeSaved,                        // callee-saved registers
     425             :       kNoCalleeSaved,                        // callee-saved fp
     426             :       CallDescriptor::kCanUseRoots | flags,  // flags
     427             :       descriptor.DebugName(),                // debug name
     428    10852160 :       descriptor.allocatable_registers());
     429             : }
     430             : 
     431             : // static
     432       44352 : CallDescriptor* Linkage::GetBytecodeDispatchCallDescriptor(
     433             :     Zone* zone, const CallInterfaceDescriptor& descriptor,
     434             :     int stack_parameter_count) {
     435             :   const int register_parameter_count = descriptor.GetRegisterParameterCount();
     436       44352 :   const int parameter_count = register_parameter_count + stack_parameter_count;
     437             : 
     438             :   DCHECK_EQ(descriptor.GetReturnCount(), 1);
     439       44352 :   LocationSignature::Builder locations(zone, 1, parameter_count);
     440             : 
     441             :   locations.AddReturn(regloc(kReturnRegister0, descriptor.GetReturnType(0)));
     442             : 
     443             :   // Add parameters in registers and on the stack.
     444      221760 :   for (int i = 0; i < parameter_count; i++) {
     445      177408 :     if (i < register_parameter_count) {
     446             :       // The first parameters go in registers.
     447             :       Register reg = descriptor.GetRegisterParameter(i);
     448             :       MachineType type = descriptor.GetParameterType(i);
     449             :       locations.AddParam(regloc(reg, type));
     450             :     } else {
     451             :       // The rest of the parameters go on the stack.
     452           0 :       int stack_slot = i - register_parameter_count - stack_parameter_count;
     453             :       locations.AddParam(LinkageLocation::ForCallerFrameSlot(
     454             :           stack_slot, MachineType::AnyTagged()));
     455             :     }
     456             :   }
     457             : 
     458             :   // The target for interpreter dispatches is a code entry address.
     459             :   MachineType target_type = MachineType::Pointer();
     460             :   LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
     461             :   const CallDescriptor::Flags kFlags =
     462             :       CallDescriptor::kCanUseRoots | CallDescriptor::kFixedTargetRegister;
     463             :   return new (zone) CallDescriptor(  // --
     464             :       CallDescriptor::kCallAddress,  // kind
     465             :       target_type,                   // target MachineType
     466             :       target_loc,                    // target location
     467             :       locations.Build(),             // location_sig
     468             :       stack_parameter_count,         // stack_parameter_count
     469             :       Operator::kNoProperties,       // properties
     470             :       kNoCalleeSaved,                // callee-saved registers
     471             :       kNoCalleeSaved,                // callee-saved fp
     472             :       kFlags,                        // flags
     473      133056 :       descriptor.DebugName());
     474             : }
     475             : 
     476       22711 : LinkageLocation Linkage::GetOsrValueLocation(int index) const {
     477       22711 :   CHECK(incoming_->IsJSFunctionCall());
     478       22711 :   int parameter_count = static_cast<int>(incoming_->JSParameterCount() - 1);
     479             :   int first_stack_slot = OsrHelper::FirstStackSlotIndex(parameter_count);
     480             : 
     481       22711 :   if (index == kOsrContextSpillSlotIndex) {
     482             :     // Context. Use the parameter location of the context spill slot.
     483             :     // Parameter (arity + 2) is special for the context of the function frame.
     484             :     // >> context_index = target + receiver + params + new_target + #args
     485        4917 :     int context_index = 1 + 1 + parameter_count + 1 + 1;
     486        4917 :     return incoming_->GetInputLocation(context_index);
     487       17794 :   } else if (index >= first_stack_slot) {
     488             :     // Local variable stored in this (callee) stack.
     489             :     int spill_index =
     490       10077 :         index - first_stack_slot + StandardFrameConstants::kFixedSlotCount;
     491             :     return LinkageLocation::ForCalleeFrameSlot(spill_index,
     492             :                                                MachineType::AnyTagged());
     493             :   } else {
     494             :     // Parameter. Use the assigned location from the incoming call descriptor.
     495        7717 :     int parameter_index = 1 + index;  // skip index 0, which is the target.
     496        7717 :     return incoming_->GetInputLocation(parameter_index);
     497             :   }
     498             : }
     499             : 
     500             : namespace {
     501             : inline bool IsTaggedReg(const LinkageLocation& loc, Register reg) {
     502     5599041 :   return loc.IsRegister() && loc.AsRegister() == reg.code() &&
     503             :          loc.GetType().representation() ==
     504             :              MachineRepresentation::kTaggedPointer;
     505             : }
     506             : }  // namespace
     507             : 
     508     3477078 : bool Linkage::ParameterHasSecondaryLocation(int index) const {
     509             :   // TODO(titzer): this should be configurable, not call-type specific.
     510     3477078 :   if (incoming_->IsJSFunctionCall()) {
     511             :     LinkageLocation loc = GetParameterLocation(index);
     512     3521589 :     return IsTaggedReg(loc, kJSFunctionRegister) ||
     513             :            IsTaggedReg(loc, kContextRegister);
     514             :   }
     515     1716301 :   if (incoming_->IsWasmFunctionCall()) {
     516             :     LinkageLocation loc = GetParameterLocation(index);
     517             :     return IsTaggedReg(loc, kWasmInstanceRegister);
     518             :   }
     519             :   return false;
     520             : }
     521             : 
     522      103591 : LinkageLocation Linkage::GetParameterSecondaryLocation(int index) const {
     523             :   // TODO(titzer): these constants are necessary due to offset/slot# mismatch
     524             :   static const int kJSContextSlot = 2 + StandardFrameConstants::kCPSlotCount;
     525             :   static const int kJSFunctionSlot = 3 + StandardFrameConstants::kCPSlotCount;
     526             :   static const int kWasmInstanceSlot = 3 + StandardFrameConstants::kCPSlotCount;
     527             : 
     528             :   DCHECK(ParameterHasSecondaryLocation(index));
     529             :   LinkageLocation loc = GetParameterLocation(index);
     530             : 
     531             :   // TODO(titzer): this should be configurable, not call-type specific.
     532      103583 :   if (incoming_->IsJSFunctionCall()) {
     533           0 :     if (IsTaggedReg(loc, kJSFunctionRegister)) {
     534             :       return LinkageLocation::ForCalleeFrameSlot(kJSFunctionSlot,
     535             :                                                  MachineType::AnyTagged());
     536             :     } else {
     537             :       DCHECK(IsTaggedReg(loc, kContextRegister));
     538             :       return LinkageLocation::ForCalleeFrameSlot(kJSContextSlot,
     539             :                                                  MachineType::AnyTagged());
     540             :     }
     541             :   }
     542      103583 :   if (incoming_->IsWasmFunctionCall()) {
     543             :     DCHECK(IsTaggedReg(loc, kWasmInstanceRegister));
     544             :     return LinkageLocation::ForCalleeFrameSlot(kWasmInstanceSlot,
     545             :                                                MachineType::AnyTagged());
     546             :   }
     547           0 :   UNREACHABLE();
     548             :   return LinkageLocation::ForCalleeFrameSlot(0, MachineType::AnyTagged());
     549             : }
     550             : 
     551             : 
     552             : }  // namespace compiler
     553             : }  // namespace internal
     554      183867 : }  // namespace v8

Generated by: LCOV version 1.10