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

Generated by: LCOV version 1.10