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/flags.h" 9 #include "src/code-stubs.h" 10 #include "src/compiler/frame.h" 11 #include "src/compiler/machine-type.h" 12 #include "src/compiler/node.h" 13 #include "src/compiler/operator.h" 14 #include "src/zone.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace compiler { 19 20 // Describes the location for a parameter or a return value to a call. 21 class LinkageLocation { 22 public: LinkageLocation(int location)23 explicit LinkageLocation(int location) : location_(location) {} 24 25 static const int16_t ANY_REGISTER = 32767; 26 AnyRegister()27 static LinkageLocation AnyRegister() { return LinkageLocation(ANY_REGISTER); } 28 29 private: 30 friend class CallDescriptor; 31 friend class OperandGenerator; 32 int16_t location_; // >= 0 implies register, otherwise stack slot. 33 }; 34 35 typedef Signature<LinkageLocation> LocationSignature; 36 37 // Describes a call to various parts of the compiler. Every call has the notion 38 // of a "target", which is the first input to the call. 39 class CallDescriptor FINAL : public ZoneObject { 40 public: 41 // Describes the kind of this call, which determines the target. 42 enum Kind { 43 kCallCodeObject, // target is a Code object 44 kCallJSFunction, // target is a JSFunction object 45 kCallAddress // target is a machine pointer 46 }; 47 48 enum Flag { 49 // TODO(jarin) kLazyDeoptimization and kNeedsFrameState should be unified. 50 kNoFlags = 0u, 51 kNeedsFrameState = 1u << 0, 52 kPatchableCallSite = 1u << 1, 53 kNeedsNopAfterCall = 1u << 2, 54 kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall 55 }; 56 typedef base::Flags<Flag> Flags; 57 58 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc, 59 MachineSignature* machine_sig, LocationSignature* location_sig, 60 size_t js_param_count, Operator::Properties properties, 61 RegList callee_saved_registers, Flags flags, 62 const char* debug_name = "") kind_(kind)63 : kind_(kind), 64 target_type_(target_type), 65 target_loc_(target_loc), 66 machine_sig_(machine_sig), 67 location_sig_(location_sig), 68 js_param_count_(js_param_count), 69 properties_(properties), 70 callee_saved_registers_(callee_saved_registers), 71 flags_(flags), 72 debug_name_(debug_name) { 73 DCHECK(machine_sig->return_count() == location_sig->return_count()); 74 DCHECK(machine_sig->parameter_count() == location_sig->parameter_count()); 75 } 76 77 // Returns the kind of this call. kind()78 Kind kind() const { return kind_; } 79 80 // Returns {true} if this descriptor is a call to a JSFunction. IsJSFunctionCall()81 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; } 82 83 // The number of return values from this call. ReturnCount()84 size_t ReturnCount() const { return machine_sig_->return_count(); } 85 86 // The number of JavaScript parameters to this call, including the receiver 87 // object. JSParameterCount()88 size_t JSParameterCount() const { return js_param_count_; } 89 90 // The total number of inputs to this call, which includes the target, 91 // receiver, context, etc. 92 // TODO(titzer): this should input the framestate input too. InputCount()93 size_t InputCount() const { return 1 + machine_sig_->parameter_count(); } 94 FrameStateCount()95 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; } 96 flags()97 Flags flags() const { return flags_; } 98 NeedsFrameState()99 bool NeedsFrameState() const { return flags() & kNeedsFrameState; } 100 GetReturnLocation(size_t index)101 LinkageLocation GetReturnLocation(size_t index) const { 102 return location_sig_->GetReturn(index); 103 } 104 GetInputLocation(size_t index)105 LinkageLocation GetInputLocation(size_t index) const { 106 if (index == 0) return target_loc_; 107 return location_sig_->GetParam(index - 1); 108 } 109 GetMachineSignature()110 const MachineSignature* GetMachineSignature() const { return machine_sig_; } 111 GetReturnType(size_t index)112 MachineType GetReturnType(size_t index) const { 113 return machine_sig_->GetReturn(index); 114 } 115 GetInputType(size_t index)116 MachineType GetInputType(size_t index) const { 117 if (index == 0) return target_type_; 118 return machine_sig_->GetParam(index - 1); 119 } 120 121 // Operator properties describe how this call can be optimized, if at all. properties()122 Operator::Properties properties() const { return properties_; } 123 124 // Get the callee-saved registers, if any, across this call. CalleeSavedRegisters()125 RegList CalleeSavedRegisters() const { return callee_saved_registers_; } 126 debug_name()127 const char* debug_name() const { return debug_name_; } 128 129 private: 130 friend class Linkage; 131 132 Kind kind_; 133 MachineType target_type_; 134 LinkageLocation target_loc_; 135 MachineSignature* machine_sig_; 136 LocationSignature* location_sig_; 137 size_t js_param_count_; 138 Operator::Properties properties_; 139 RegList callee_saved_registers_; 140 Flags flags_; 141 const char* debug_name_; 142 }; 143 144 DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags) 145 146 OStream& operator<<(OStream& os, const CallDescriptor& d); 147 OStream& operator<<(OStream& os, const CallDescriptor::Kind& k); 148 149 // Defines the linkage for a compilation, including the calling conventions 150 // for incoming parameters and return value(s) as well as the outgoing calling 151 // convention for any kind of call. Linkage is generally architecture-specific. 152 // 153 // Can be used to translate {arg_index} (i.e. index of the call node input) as 154 // well as {param_index} (i.e. as stored in parameter nodes) into an operator 155 // representing the architecture-specific location. The following call node 156 // layouts are supported (where {n} is the number value inputs): 157 // 158 // #0 #1 #2 #3 [...] #n 159 // Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context 160 // Call[JSFunction] function, rcvr, arg 1, arg 2, [...], context 161 // Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context 162 class Linkage : public ZoneObject { 163 public: 164 explicit Linkage(CompilationInfo* info); Linkage(CompilationInfo * info,CallDescriptor * incoming)165 explicit Linkage(CompilationInfo* info, CallDescriptor* incoming) 166 : info_(info), incoming_(incoming) {} 167 168 // The call descriptor for this compilation unit describes the locations 169 // of incoming parameters and the outgoing return value(s). GetIncomingDescriptor()170 CallDescriptor* GetIncomingDescriptor() { return incoming_; } 171 CallDescriptor* GetJSCallDescriptor(int parameter_count); 172 static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone); 173 CallDescriptor* GetRuntimeCallDescriptor(Runtime::FunctionId function, 174 int parameter_count, 175 Operator::Properties properties); 176 static CallDescriptor* GetRuntimeCallDescriptor( 177 Runtime::FunctionId function, int parameter_count, 178 Operator::Properties properties, Zone* zone); 179 180 CallDescriptor* GetStubCallDescriptor( 181 CallInterfaceDescriptor descriptor, int stack_parameter_count = 0, 182 CallDescriptor::Flags flags = CallDescriptor::kNoFlags); 183 static CallDescriptor* GetStubCallDescriptor( 184 CallInterfaceDescriptor descriptor, int stack_parameter_count, 185 CallDescriptor::Flags flags, Zone* zone); 186 187 // Creates a call descriptor for simplified C calls that is appropriate 188 // for the host platform. This simplified calling convention only supports 189 // integers and pointers of one word size each, i.e. no floating point, 190 // structs, pointers to members, etc. 191 static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone, 192 MachineSignature* sig); 193 194 // Get the location of an (incoming) parameter to this function. GetParameterLocation(int index)195 LinkageLocation GetParameterLocation(int index) { 196 return incoming_->GetInputLocation(index + 1); // + 1 to skip target. 197 } 198 199 // Get the machine type of an (incoming) parameter to this function. GetParameterType(int index)200 MachineType GetParameterType(int index) { 201 return incoming_->GetInputType(index + 1); // + 1 to skip target. 202 } 203 204 // Get the location where this function should place its return value. GetReturnLocation()205 LinkageLocation GetReturnLocation() { 206 return incoming_->GetReturnLocation(0); 207 } 208 209 // Get the machine type of this function's return value. GetReturnType()210 MachineType GetReturnType() { return incoming_->GetReturnType(0); } 211 212 // Get the frame offset for a given spill slot. The location depends on the 213 // calling convention and the specific frame layout, and may thus be 214 // architecture-specific. Negative spill slots indicate arguments on the 215 // caller's frame. The {extra} parameter indicates an additional offset from 216 // the frame offset, e.g. to index into part of a double slot. 217 FrameOffset GetFrameOffset(int spill_slot, Frame* frame, int extra = 0); 218 info()219 CompilationInfo* info() const { return info_; } 220 221 static bool NeedsFrameState(Runtime::FunctionId function); 222 223 private: 224 CompilationInfo* info_; 225 CallDescriptor* incoming_; 226 }; 227 228 } // namespace compiler 229 } // namespace internal 230 } // namespace v8 231 232 #endif // V8_COMPILER_LINKAGE_H_ 233