Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame^] | 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: |
| 23 | explicit LinkageLocation(int location) : location_(location) {} |
| 24 | |
| 25 | static const int16_t ANY_REGISTER = 32767; |
| 26 | |
| 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 = "") |
| 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. |
| 78 | Kind kind() const { return kind_; } |
| 79 | |
| 80 | // Returns {true} if this descriptor is a call to a JSFunction. |
| 81 | bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; } |
| 82 | |
| 83 | // The number of return values from this call. |
| 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. |
| 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. |
| 93 | size_t InputCount() const { return 1 + machine_sig_->parameter_count(); } |
| 94 | |
| 95 | size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; } |
| 96 | |
| 97 | Flags flags() const { return flags_; } |
| 98 | |
| 99 | bool NeedsFrameState() const { return flags() & kNeedsFrameState; } |
| 100 | |
| 101 | LinkageLocation GetReturnLocation(size_t index) const { |
| 102 | return location_sig_->GetReturn(index); |
| 103 | } |
| 104 | |
| 105 | LinkageLocation GetInputLocation(size_t index) const { |
| 106 | if (index == 0) return target_loc_; |
| 107 | return location_sig_->GetParam(index - 1); |
| 108 | } |
| 109 | |
| 110 | const MachineSignature* GetMachineSignature() const { return machine_sig_; } |
| 111 | |
| 112 | MachineType GetReturnType(size_t index) const { |
| 113 | return machine_sig_->GetReturn(index); |
| 114 | } |
| 115 | |
| 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. |
| 122 | Operator::Properties properties() const { return properties_; } |
| 123 | |
| 124 | // Get the callee-saved registers, if any, across this call. |
| 125 | RegList CalleeSavedRegisters() const { return callee_saved_registers_; } |
| 126 | |
| 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); |
| 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). |
| 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. |
| 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. |
| 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. |
| 205 | LinkageLocation GetReturnLocation() { |
| 206 | return incoming_->GetReturnLocation(0); |
| 207 | } |
| 208 | |
| 209 | // Get the machine type of this function's return value. |
| 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 | |
| 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_ |