LCOV - code coverage report
Current view: top level - src/compiler - linkage.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 114 134 85.1 %
Date: 2019-04-17 Functions: 19 21 90.5 %

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

Generated by: LCOV version 1.10