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

Generated by: LCOV version 1.10