LCOV - code coverage report
Current view: top level - src/compiler - linkage.h (source / functions) Hit Total Coverage
Test: app.info Lines: 30 32 93.8 %
Date: 2019-04-17 Functions: 1 1 100.0 %

          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             : #ifndef V8_COMPILER_LINKAGE_H_
       6             : #define V8_COMPILER_LINKAGE_H_
       7             : 
       8             : #include "src/base/compiler-specific.h"
       9             : #include "src/base/flags.h"
      10             : #include "src/compiler/frame.h"
      11             : #include "src/compiler/operator.h"
      12             : #include "src/globals.h"
      13             : #include "src/interface-descriptors.h"
      14             : #include "src/machine-type.h"
      15             : #include "src/register-arch.h"
      16             : #include "src/reglist.h"
      17             : #include "src/runtime/runtime.h"
      18             : #include "src/signature.h"
      19             : #include "src/zone/zone.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : 
      24             : class CallInterfaceDescriptor;
      25             : class OptimizedCompilationInfo;
      26             : 
      27             : namespace compiler {
      28             : 
      29             : const RegList kNoCalleeSaved = 0;
      30             : 
      31             : class Node;
      32             : class OsrHelper;
      33             : 
      34             : // Describes the location for a parameter or a return value to a call.
      35             : class LinkageLocation {
      36             :  public:
      37             :   bool operator==(const LinkageLocation& other) const {
      38           0 :     return bit_field_ == other.bit_field_;
      39             :   }
      40             : 
      41             :   bool operator!=(const LinkageLocation& other) const {
      42             :     return !(*this == other);
      43             :   }
      44             : 
      45             :   static LinkageLocation ForAnyRegister(
      46             :       MachineType type = MachineType::None()) {
      47             :     return LinkageLocation(REGISTER, ANY_REGISTER, type);
      48             :   }
      49             : 
      50             :   static LinkageLocation ForRegister(int32_t reg,
      51             :                                      MachineType type = MachineType::None()) {
      52             :     DCHECK_LE(0, reg);
      53             :     return LinkageLocation(REGISTER, reg, type);
      54             :   }
      55             : 
      56             :   static LinkageLocation ForCallerFrameSlot(int32_t slot, MachineType type) {
      57             :     DCHECK_GT(0, slot);
      58             :     return LinkageLocation(STACK_SLOT, slot, type);
      59             :   }
      60             : 
      61             :   static LinkageLocation ForCalleeFrameSlot(int32_t slot, MachineType type) {
      62             :     // TODO(titzer): bailout instead of crashing here.
      63             :     DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT);
      64             :     return LinkageLocation(STACK_SLOT, slot, type);
      65             :   }
      66             : 
      67             :   static LinkageLocation ForSavedCallerReturnAddress() {
      68             :     return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
      69             :                                StandardFrameConstants::kCallerPCOffset) /
      70             :                                   kSystemPointerSize,
      71             :                               MachineType::Pointer());
      72             :   }
      73             : 
      74             :   static LinkageLocation ForSavedCallerFramePtr() {
      75             :     return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
      76             :                                StandardFrameConstants::kCallerFPOffset) /
      77             :                                   kSystemPointerSize,
      78             :                               MachineType::Pointer());
      79             :   }
      80             : 
      81             :   static LinkageLocation ForSavedCallerConstantPool() {
      82             :     DCHECK(V8_EMBEDDED_CONSTANT_POOL);
      83             :     return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
      84             :                                StandardFrameConstants::kConstantPoolOffset) /
      85             :                                   kSystemPointerSize,
      86             :                               MachineType::AnyTagged());
      87             :   }
      88             : 
      89             :   static LinkageLocation ForSavedCallerFunction() {
      90             :     return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
      91             :                                StandardFrameConstants::kFunctionOffset) /
      92             :                                   kSystemPointerSize,
      93             :                               MachineType::AnyTagged());
      94             :   }
      95             : 
      96             :   static LinkageLocation ConvertToTailCallerLocation(
      97             :       LinkageLocation caller_location, int stack_param_delta) {
      98      521597 :     if (!caller_location.IsRegister()) {
      99             :       return LinkageLocation(STACK_SLOT,
     100             :                              caller_location.GetLocation() + stack_param_delta,
     101       59152 :                              caller_location.GetType());
     102             :     }
     103             :     return caller_location;
     104             :   }
     105             : 
     106             :   MachineType GetType() const { return machine_type_; }
     107             : 
     108             :   int GetSize() const {
     109      152900 :     return 1 << ElementSizeLog2Of(GetType().representation());
     110             :   }
     111             : 
     112             :   int GetSizeInPointers() const {
     113             :     // Round up
     114      152900 :     return (GetSize() + kSystemPointerSize - 1) / kSystemPointerSize;
     115             :   }
     116             : 
     117             :   int32_t GetLocation() const {
     118             :     // We can't use LocationField::decode here because it doesn't work for
     119             :     // negative values!
     120             :     return static_cast<int32_t>(bit_field_ & LocationField::kMask) >>
     121    69337430 :            LocationField::kShift;
     122             :   }
     123             : 
     124    47248893 :   bool IsRegister() const { return TypeField::decode(bit_field_) == REGISTER; }
     125             :   bool IsAnyRegister() const {
     126    60678984 :     return IsRegister() && GetLocation() == ANY_REGISTER;
     127             :   }
     128    43589608 :   bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; }
     129    28144778 :   bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; }
     130             : 
     131             :   int32_t AsRegister() const {
     132             :     DCHECK(IsRegister());
     133             :     return GetLocation();
     134             :   }
     135             :   int32_t AsCallerFrameSlot() const {
     136             :     DCHECK(IsCallerFrameSlot());
     137             :     return GetLocation();
     138             :   }
     139             :   int32_t AsCalleeFrameSlot() const {
     140             :     DCHECK(IsCalleeFrameSlot());
     141             :     return GetLocation();
     142             :   }
     143             : 
     144             :  private:
     145             :   enum LocationType { REGISTER, STACK_SLOT };
     146             : 
     147             :   class TypeField : public BitField<LocationType, 0, 1> {};
     148             :   class LocationField : public BitField<int32_t, TypeField::kNext, 31> {};
     149             : 
     150             :   static constexpr int32_t ANY_REGISTER = -1;
     151             :   static constexpr int32_t MAX_STACK_SLOT = 32767;
     152             : 
     153             :   LinkageLocation(LocationType type, int32_t location,
     154             :                   MachineType machine_type) {
     155     5235336 :     bit_field_ = TypeField::encode(type) |
     156             :                  // {location} can be -1 (ANY_REGISTER).
     157    18864691 :                  ((static_cast<uint32_t>(location) << LocationField::kShift) &
     158    18864691 :                   LocationField::kMask);
     159             :     machine_type_ = machine_type;
     160             :   }
     161             : 
     162             :   int32_t bit_field_;
     163             :   MachineType machine_type_;
     164             : };
     165             : 
     166             : using LocationSignature = Signature<LinkageLocation>;
     167             : 
     168             : // Describes a call to various parts of the compiler. Every call has the notion
     169             : // of a "target", which is the first input to the call.
     170             : class V8_EXPORT_PRIVATE CallDescriptor final
     171             :     : public NON_EXPORTED_BASE(ZoneObject) {
     172             :  public:
     173             :   // Describes the kind of this call, which determines the target.
     174             :   enum Kind {
     175             :     kCallCodeObject,         // target is a Code object
     176             :     kCallJSFunction,         // target is a JSFunction object
     177             :     kCallAddress,            // target is a machine pointer
     178             :     kCallWasmFunction,       // target is a wasm function
     179             :     kCallWasmImportWrapper,  // target is a wasm import wrapper
     180             :     kCallBuiltinPointer,     // target is a builtin pointer
     181             :   };
     182             : 
     183             :   enum Flag {
     184             :     kNoFlags = 0u,
     185             :     kNeedsFrameState = 1u << 0,
     186             :     kHasExceptionHandler = 1u << 1,
     187             :     kCanUseRoots = 1u << 2,
     188             :     // Causes the code generator to initialize the root register.
     189             :     kInitializeRootRegister = 1u << 3,
     190             :     // Does not ever try to allocate space on our heap.
     191             :     kNoAllocate = 1u << 4,
     192             :     // Push argument count as part of function prologue.
     193             :     kPushArgumentCount = 1u << 5,
     194             :     // Use retpoline for this call if indirect.
     195             :     kRetpoline = 1u << 6,
     196             :     // Use the kJavaScriptCallCodeStartRegister (fixed) register for the
     197             :     // indirect target address when calling.
     198             :     kFixedTargetRegister = 1u << 7,
     199             :     kAllowCallThroughSlot = 1u << 8
     200             :   };
     201             :   using Flags = base::Flags<Flag>;
     202             : 
     203             :   CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc,
     204             :                  LocationSignature* location_sig, size_t stack_param_count,
     205             :                  Operator::Properties properties,
     206             :                  RegList callee_saved_registers,
     207             :                  RegList callee_saved_fp_registers, Flags flags,
     208             :                  const char* debug_name = "",
     209             :                  const RegList allocatable_registers = 0,
     210             :                  size_t stack_return_count = 0)
     211             :       : kind_(kind),
     212             :         target_type_(target_type),
     213             :         target_loc_(target_loc),
     214             :         location_sig_(location_sig),
     215             :         stack_param_count_(stack_param_count),
     216             :         stack_return_count_(stack_return_count),
     217             :         properties_(properties),
     218             :         callee_saved_registers_(callee_saved_registers),
     219             :         callee_saved_fp_registers_(callee_saved_fp_registers),
     220             :         allocatable_registers_(allocatable_registers),
     221             :         flags_(flags),
     222     8792587 :         debug_name_(debug_name) {}
     223             : 
     224             :   // Returns the kind of this call.
     225             :   Kind kind() const { return kind_; }
     226             : 
     227             :   // Returns {true} if this descriptor is a call to a C function.
     228             :   bool IsCFunctionCall() const { return kind_ == kCallAddress; }
     229             : 
     230             :   // Returns {true} if this descriptor is a call to a JSFunction.
     231           5 :   bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
     232             : 
     233             :   // Returns {true} if this descriptor is a call to a WebAssembly function.
     234             :   bool IsWasmFunctionCall() const { return kind_ == kCallWasmFunction; }
     235             : 
     236             :   // Returns {true} if this descriptor is a call to a WebAssembly function.
     237             :   bool IsWasmImportWrapper() const { return kind_ == kCallWasmImportWrapper; }
     238             : 
     239             :   bool RequiresFrameAsIncoming() const {
     240     2643550 :     return IsCFunctionCall() || IsJSFunctionCall() || IsWasmFunctionCall();
     241             :   }
     242             : 
     243             :   // The number of return values from this call.
     244             :   size_t ReturnCount() const { return location_sig_->return_count(); }
     245             : 
     246             :   // The number of C parameters to this call.
     247             :   size_t ParameterCount() const { return location_sig_->parameter_count(); }
     248             : 
     249             :   // The number of stack parameters to the call.
     250             :   size_t StackParameterCount() const { return stack_param_count_; }
     251             : 
     252             :   // The number of stack return values from the call.
     253             :   size_t StackReturnCount() const { return stack_return_count_; }
     254             : 
     255             :   // The number of parameters to the JS function call.
     256             :   size_t JSParameterCount() const {
     257             :     DCHECK(IsJSFunctionCall());
     258             :     return stack_param_count_;
     259             :   }
     260             : 
     261             :   // The total number of inputs to this call, which includes the target,
     262             :   // receiver, context, etc.
     263             :   // TODO(titzer): this should input the framestate input too.
     264    37268031 :   size_t InputCount() const { return 1 + location_sig_->parameter_count(); }
     265             : 
     266     5714525 :   size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
     267             : 
     268             :   Flags flags() const { return flags_; }
     269             : 
     270             :   bool NeedsFrameState() const { return flags() & kNeedsFrameState; }
     271             :   bool PushArgumentCount() const { return flags() & kPushArgumentCount; }
     272             :   bool InitializeRootRegister() const {
     273             :     return flags() & kInitializeRootRegister;
     274             :   }
     275             : 
     276             :   LinkageLocation GetReturnLocation(size_t index) const {
     277             :     return location_sig_->GetReturn(index);
     278             :   }
     279             : 
     280             :   LinkageLocation GetInputLocation(size_t index) const {
     281    32745977 :     if (index == 0) return target_loc_;
     282    31124101 :     return location_sig_->GetParam(index - 1);
     283             :   }
     284             : 
     285             :   MachineSignature* GetMachineSignature(Zone* zone) const;
     286             : 
     287             :   MachineType GetReturnType(size_t index) const {
     288             :     return location_sig_->GetReturn(index).GetType();
     289             :   }
     290             : 
     291             :   MachineType GetInputType(size_t index) const {
     292     5468187 :     if (index == 0) return target_type_;
     293     5300089 :     return location_sig_->GetParam(index - 1).GetType();
     294             :   }
     295             : 
     296             :   MachineType GetParameterType(size_t index) const {
     297             :     return location_sig_->GetParam(index).GetType();
     298             :   }
     299             : 
     300             :   // Operator properties describe how this call can be optimized, if at all.
     301             :   Operator::Properties properties() const { return properties_; }
     302             : 
     303             :   // Get the callee-saved registers, if any, across this call.
     304             :   RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
     305             : 
     306             :   // Get the callee-saved FP registers, if any, across this call.
     307             :   RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
     308             : 
     309             :   const char* debug_name() const { return debug_name_; }
     310             : 
     311             :   bool UsesOnlyRegisters() const;
     312             : 
     313             :   bool HasSameReturnLocationsAs(const CallDescriptor* other) const;
     314             : 
     315             :   // Returns the first stack slot that is not used by the stack parameters.
     316             :   int GetFirstUnusedStackSlot() const;
     317             : 
     318             :   int GetStackParameterDelta(const CallDescriptor* tail_caller) const;
     319             : 
     320             :   int GetTaggedParameterSlots() const;
     321             : 
     322             :   bool CanTailCall(const Node* call) const;
     323             : 
     324             :   int CalculateFixedFrameSize() const;
     325             : 
     326             :   RegList AllocatableRegisters() const { return allocatable_registers_; }
     327             : 
     328             :   bool HasRestrictedAllocatableRegisters() const {
     329             :     return allocatable_registers_ != 0;
     330             :   }
     331             : 
     332         452 :   void set_save_fp_mode(SaveFPRegsMode mode) { save_fp_mode_ = mode; }
     333             : 
     334             :   SaveFPRegsMode get_save_fp_mode() const { return save_fp_mode_; }
     335             : 
     336             :  private:
     337             :   friend class Linkage;
     338             :   SaveFPRegsMode save_fp_mode_ = kSaveFPRegs;
     339             : 
     340             :   const Kind kind_;
     341             :   const MachineType target_type_;
     342             :   const LinkageLocation target_loc_;
     343             :   const LocationSignature* const location_sig_;
     344             :   const size_t stack_param_count_;
     345             :   const size_t stack_return_count_;
     346             :   const Operator::Properties properties_;
     347             :   const RegList callee_saved_registers_;
     348             :   const RegList callee_saved_fp_registers_;
     349             :   // Non-zero value means restricting the set of allocatable registers for
     350             :   // register allocator to use.
     351             :   const RegList allocatable_registers_;
     352             :   const Flags flags_;
     353             :   const char* const debug_name_;
     354             : 
     355             :   DISALLOW_COPY_AND_ASSIGN(CallDescriptor);
     356             : };
     357             : 
     358             : DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags)
     359             : 
     360             : std::ostream& operator<<(std::ostream& os, const CallDescriptor& d);
     361             : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
     362             :                                            const CallDescriptor::Kind& k);
     363             : 
     364             : // Defines the linkage for a compilation, including the calling conventions
     365             : // for incoming parameters and return value(s) as well as the outgoing calling
     366             : // convention for any kind of call. Linkage is generally architecture-specific.
     367             : //
     368             : // Can be used to translate {arg_index} (i.e. index of the call node input) as
     369             : // well as {param_index} (i.e. as stored in parameter nodes) into an operator
     370             : // representing the architecture-specific location. The following call node
     371             : // layouts are supported (where {n} is the number of value inputs):
     372             : //
     373             : //                        #0          #1     #2     [...]             #n
     374             : // Call[CodeStub]         code,       arg 1, arg 2, [...],            context
     375             : // Call[JSFunction]       function,   rcvr,  arg 1, [...], new, #arg, context
     376             : // Call[Runtime]          CEntry,     arg 1, arg 2, [...], fun, #arg, context
     377             : // Call[BytecodeDispatch] address,    arg 1, arg 2, [...]
     378             : class V8_EXPORT_PRIVATE Linkage : public NON_EXPORTED_BASE(ZoneObject) {
     379             :  public:
     380     2641133 :   explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {}
     381             : 
     382             :   static CallDescriptor* ComputeIncoming(Zone* zone,
     383             :                                          OptimizedCompilationInfo* info);
     384             : 
     385             :   // The call descriptor for this compilation unit describes the locations
     386             :   // of incoming parameters and the outgoing return value(s).
     387    35104582 :   CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
     388             :   static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
     389             :                                              int parameter_count,
     390             :                                              CallDescriptor::Flags flags);
     391             : 
     392             :   static CallDescriptor* GetRuntimeCallDescriptor(
     393             :       Zone* zone, Runtime::FunctionId function, int js_parameter_count,
     394             :       Operator::Properties properties, CallDescriptor::Flags flags);
     395             : 
     396             :   static CallDescriptor* GetCEntryStubCallDescriptor(
     397             :       Zone* zone, int return_count, int js_parameter_count,
     398             :       const char* debug_name, Operator::Properties properties,
     399             :       CallDescriptor::Flags flags);
     400             : 
     401             :   static CallDescriptor* GetStubCallDescriptor(
     402             :       Zone* zone, const CallInterfaceDescriptor& descriptor,
     403             :       int stack_parameter_count, CallDescriptor::Flags flags,
     404             :       Operator::Properties properties = Operator::kNoProperties,
     405             :       StubCallMode stub_mode = StubCallMode::kCallCodeObject);
     406             : 
     407             :   static CallDescriptor* GetBytecodeDispatchCallDescriptor(
     408             :       Zone* zone, const CallInterfaceDescriptor& descriptor,
     409             :       int stack_parameter_count);
     410             : 
     411             :   // Creates a call descriptor for simplified C calls that is appropriate
     412             :   // for the host platform. This simplified calling convention only supports
     413             :   // integers and pointers of one word size each, i.e. no floating point,
     414             :   // structs, pointers to members, etc.
     415             :   static CallDescriptor* GetSimplifiedCDescriptor(
     416             :       Zone* zone, const MachineSignature* sig,
     417             :       bool set_initialize_root_flag = false);
     418             : 
     419             :   // Get the location of an (incoming) parameter to this function.
     420     6850905 :   LinkageLocation GetParameterLocation(int index) const {
     421    13701810 :     return incoming_->GetInputLocation(index + 1);  // + 1 to skip target.
     422             :   }
     423             : 
     424             :   // Get the machine type of an (incoming) parameter to this function.
     425             :   MachineType GetParameterType(int index) const {
     426     3740502 :     return incoming_->GetInputType(index + 1);  // + 1 to skip target.
     427             :   }
     428             : 
     429             :   // Get the location where this function should place its return value.
     430             :   LinkageLocation GetReturnLocation(size_t index = 0) const {
     431     2773946 :     return incoming_->GetReturnLocation(index);
     432             :   }
     433             : 
     434             :   // Get the machine type of this function's return value.
     435             :   MachineType GetReturnType(size_t index = 0) const {
     436           0 :     return incoming_->GetReturnType(index);
     437             :   }
     438             : 
     439             :   bool ParameterHasSecondaryLocation(int index) const;
     440             :   LinkageLocation GetParameterSecondaryLocation(int index) const;
     441             : 
     442             :   static bool NeedsFrameStateInput(Runtime::FunctionId function);
     443             : 
     444             :   // Get the location where an incoming OSR value is stored.
     445             :   LinkageLocation GetOsrValueLocation(int index) const;
     446             : 
     447             :   // A special {Parameter} index for Stub Calls that represents context.
     448             :   static int GetStubCallContextParamIndex(int parameter_count) {
     449             :     return parameter_count + 0;  // Parameter (arity + 0) is special.
     450             :   }
     451             : 
     452             :   // A special {Parameter} index for JSCalls that represents the new target.
     453             :   static int GetJSCallNewTargetParamIndex(int parameter_count) {
     454             :     return parameter_count + 0;  // Parameter (arity + 0) is special.
     455             :   }
     456             : 
     457             :   // A special {Parameter} index for JSCalls that represents the argument count.
     458             :   static int GetJSCallArgCountParamIndex(int parameter_count) {
     459     1496070 :     return parameter_count + 1;  // Parameter (arity + 1) is special.
     460             :   }
     461             : 
     462             :   // A special {Parameter} index for JSCalls that represents the context.
     463             :   static int GetJSCallContextParamIndex(int parameter_count) {
     464     2186449 :     return parameter_count + 2;  // Parameter (arity + 2) is special.
     465             :   }
     466             : 
     467             :   // A special {Parameter} index for JSCalls that represents the closure.
     468             :   static const int kJSCallClosureParamIndex = -1;
     469             : 
     470             :   // A special {OsrValue} index to indicate the context spill slot.
     471             :   static const int kOsrContextSpillSlotIndex = -1;
     472             : 
     473             :   // A special {OsrValue} index to indicate the accumulator register.
     474             :   static const int kOsrAccumulatorRegisterIndex = -1;
     475             : 
     476             :  private:
     477             :   CallDescriptor* const incoming_;
     478             : 
     479             :   DISALLOW_COPY_AND_ASSIGN(Linkage);
     480             : };
     481             : 
     482             : }  // namespace compiler
     483             : }  // namespace internal
     484             : }  // namespace v8
     485             : 
     486             : #endif  // V8_COMPILER_LINKAGE_H_

Generated by: LCOV version 1.10