OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_LINKAGE_H_ | 5 #ifndef V8_COMPILER_LINKAGE_H_ |
6 #define V8_COMPILER_LINKAGE_H_ | 6 #define V8_COMPILER_LINKAGE_H_ |
7 | 7 |
8 #include "src/base/flags.h" | 8 #include "src/base/flags.h" |
9 #include "src/compiler/frame.h" | 9 #include "src/compiler/frame.h" |
10 #include "src/compiler/operator.h" | 10 #include "src/compiler/operator.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 class LinkageLocation { | 30 class LinkageLocation { |
31 public: | 31 public: |
32 bool operator==(const LinkageLocation& other) const { | 32 bool operator==(const LinkageLocation& other) const { |
33 return bit_field_ == other.bit_field_; | 33 return bit_field_ == other.bit_field_; |
34 } | 34 } |
35 | 35 |
36 bool operator!=(const LinkageLocation& other) const { | 36 bool operator!=(const LinkageLocation& other) const { |
37 return !(*this == other); | 37 return !(*this == other); |
38 } | 38 } |
39 | 39 |
40 static LinkageLocation ForAnyRegister() { | 40 static LinkageLocation ForAnyRegister( |
41 return LinkageLocation(REGISTER, ANY_REGISTER); | 41 MachineType type = MachineType::None()) { |
| 42 return LinkageLocation(REGISTER, ANY_REGISTER, type); |
42 } | 43 } |
43 | 44 |
44 static LinkageLocation ForRegister(int32_t reg) { | 45 static LinkageLocation ForRegister(int32_t reg, |
| 46 MachineType type = MachineType::None()) { |
45 DCHECK(reg >= 0); | 47 DCHECK(reg >= 0); |
46 return LinkageLocation(REGISTER, reg); | 48 return LinkageLocation(REGISTER, reg, type); |
47 } | 49 } |
48 | 50 |
49 static LinkageLocation ForCallerFrameSlot(int32_t slot) { | 51 static LinkageLocation ForCallerFrameSlot(int32_t slot, MachineType type) { |
50 DCHECK(slot < 0); | 52 DCHECK(slot < 0); |
51 return LinkageLocation(STACK_SLOT, slot); | 53 return LinkageLocation(STACK_SLOT, slot, type); |
52 } | 54 } |
53 | 55 |
54 static LinkageLocation ForCalleeFrameSlot(int32_t slot) { | 56 static LinkageLocation ForCalleeFrameSlot(int32_t slot, MachineType type) { |
55 // TODO(titzer): bailout instead of crashing here. | 57 // TODO(titzer): bailout instead of crashing here. |
56 DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT); | 58 DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT); |
57 return LinkageLocation(STACK_SLOT, slot); | 59 return LinkageLocation(STACK_SLOT, slot, type); |
58 } | 60 } |
59 | 61 |
60 static LinkageLocation ForSavedCallerReturnAddress() { | 62 static LinkageLocation ForSavedCallerReturnAddress() { |
61 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - | 63 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - |
62 StandardFrameConstants::kCallerPCOffset) / | 64 StandardFrameConstants::kCallerPCOffset) / |
63 kPointerSize); | 65 kPointerSize, |
| 66 MachineType::Pointer()); |
64 } | 67 } |
65 | 68 |
66 static LinkageLocation ForSavedCallerFramePtr() { | 69 static LinkageLocation ForSavedCallerFramePtr() { |
67 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - | 70 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - |
68 StandardFrameConstants::kCallerFPOffset) / | 71 StandardFrameConstants::kCallerFPOffset) / |
69 kPointerSize); | 72 kPointerSize, |
| 73 MachineType::Pointer()); |
70 } | 74 } |
71 | 75 |
72 static LinkageLocation ForSavedCallerConstantPool() { | 76 static LinkageLocation ForSavedCallerConstantPool() { |
73 DCHECK(V8_EMBEDDED_CONSTANT_POOL); | 77 DCHECK(V8_EMBEDDED_CONSTANT_POOL); |
74 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - | 78 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - |
75 StandardFrameConstants::kConstantPoolOffset) / | 79 StandardFrameConstants::kConstantPoolOffset) / |
76 kPointerSize); | 80 kPointerSize, |
| 81 MachineType::AnyTagged()); |
77 } | 82 } |
78 | 83 |
79 static LinkageLocation ForSavedCallerFunction() { | 84 static LinkageLocation ForSavedCallerFunction() { |
80 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - | 85 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - |
81 StandardFrameConstants::kFunctionOffset) / | 86 StandardFrameConstants::kFunctionOffset) / |
82 kPointerSize); | 87 kPointerSize, |
| 88 MachineType::AnyTagged()); |
83 } | 89 } |
84 | 90 |
85 static LinkageLocation ConvertToTailCallerLocation( | 91 static LinkageLocation ConvertToTailCallerLocation( |
86 LinkageLocation caller_location, int stack_param_delta) { | 92 LinkageLocation caller_location, int stack_param_delta) { |
87 if (!caller_location.IsRegister()) { | 93 if (!caller_location.IsRegister()) { |
88 return LinkageLocation(STACK_SLOT, | 94 return LinkageLocation(STACK_SLOT, |
89 caller_location.GetLocation() + stack_param_delta); | 95 caller_location.GetLocation() + stack_param_delta, |
| 96 caller_location.GetType()); |
90 } | 97 } |
91 return caller_location; | 98 return caller_location; |
92 } | 99 } |
93 | 100 |
94 private: | 101 private: |
95 friend class CallDescriptor; | 102 friend class CallDescriptor; |
96 friend class OperandGenerator; | 103 friend class OperandGenerator; |
97 | 104 |
98 enum LocationType { REGISTER, STACK_SLOT }; | 105 enum LocationType { REGISTER, STACK_SLOT }; |
99 | 106 |
100 class TypeField : public BitField<LocationType, 0, 1> {}; | 107 class TypeField : public BitField<LocationType, 0, 1> {}; |
101 class LocationField : public BitField<int32_t, TypeField::kNext, 31> {}; | 108 class LocationField : public BitField<int32_t, TypeField::kNext, 31> {}; |
102 | 109 |
103 static const int32_t ANY_REGISTER = -1; | 110 static const int32_t ANY_REGISTER = -1; |
104 static const int32_t MAX_STACK_SLOT = 32767; | 111 static const int32_t MAX_STACK_SLOT = 32767; |
105 | 112 |
106 LinkageLocation(LocationType type, int32_t location) { | 113 LinkageLocation(LocationType type, int32_t location, |
| 114 MachineType machine_type) { |
107 bit_field_ = TypeField::encode(type) | | 115 bit_field_ = TypeField::encode(type) | |
108 ((location << LocationField::kShift) & LocationField::kMask); | 116 ((location << LocationField::kShift) & LocationField::kMask); |
| 117 machine_type_ = machine_type; |
| 118 } |
| 119 |
| 120 MachineType GetType() const { return machine_type_; } |
| 121 |
| 122 int GetSize() const { |
| 123 return 1 << ElementSizeLog2Of(GetType().representation()); |
| 124 } |
| 125 |
| 126 int GetSizeInPointers() const { |
| 127 // Round up |
| 128 return (GetSize() + kPointerSize - 1) / kPointerSize; |
109 } | 129 } |
110 | 130 |
111 int32_t GetLocation() const { | 131 int32_t GetLocation() const { |
112 return static_cast<int32_t>(bit_field_ & LocationField::kMask) >> | 132 return static_cast<int32_t>(bit_field_ & LocationField::kMask) >> |
113 LocationField::kShift; | 133 LocationField::kShift; |
114 } | 134 } |
115 | 135 |
116 bool IsRegister() const { return TypeField::decode(bit_field_) == REGISTER; } | 136 bool IsRegister() const { return TypeField::decode(bit_field_) == REGISTER; } |
117 bool IsAnyRegister() const { | 137 bool IsAnyRegister() const { |
118 return IsRegister() && GetLocation() == ANY_REGISTER; | 138 return IsRegister() && GetLocation() == ANY_REGISTER; |
119 } | 139 } |
120 bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; } | 140 bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; } |
121 bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; } | 141 bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; } |
122 | 142 |
123 int32_t AsRegister() const { | 143 int32_t AsRegister() const { |
124 DCHECK(IsRegister()); | 144 DCHECK(IsRegister()); |
125 return GetLocation(); | 145 return GetLocation(); |
126 } | 146 } |
127 int32_t AsCallerFrameSlot() const { | 147 int32_t AsCallerFrameSlot() const { |
128 DCHECK(IsCallerFrameSlot()); | 148 DCHECK(IsCallerFrameSlot()); |
129 return GetLocation(); | 149 return GetLocation(); |
130 } | 150 } |
131 int32_t AsCalleeFrameSlot() const { | 151 int32_t AsCalleeFrameSlot() const { |
132 DCHECK(IsCalleeFrameSlot()); | 152 DCHECK(IsCalleeFrameSlot()); |
133 return GetLocation(); | 153 return GetLocation(); |
134 } | 154 } |
135 | 155 |
136 int32_t bit_field_; | 156 int32_t bit_field_; |
| 157 MachineType machine_type_; |
137 }; | 158 }; |
138 | 159 |
139 typedef Signature<LinkageLocation> LocationSignature; | 160 typedef Signature<LinkageLocation> LocationSignature; |
140 | 161 |
141 // Describes a call to various parts of the compiler. Every call has the notion | 162 // Describes a call to various parts of the compiler. Every call has the notion |
142 // of a "target", which is the first input to the call. | 163 // of a "target", which is the first input to the call. |
143 class CallDescriptor final : public ZoneObject { | 164 class CallDescriptor final : public ZoneObject { |
144 public: | 165 public: |
145 // Describes the kind of this call, which determines the target. | 166 // Describes the kind of this call, which determines the target. |
146 enum Kind { | 167 enum Kind { |
(...skipping 15 matching lines...) Expand all Loading... |
162 kRestoreJSSP = 1u << 6, | 183 kRestoreJSSP = 1u << 6, |
163 kRestoreCSP = 1u << 7, | 184 kRestoreCSP = 1u << 7, |
164 // Causes the code generator to initialize the root register. | 185 // Causes the code generator to initialize the root register. |
165 kInitializeRootRegister = 1u << 8, | 186 kInitializeRootRegister = 1u << 8, |
166 // Does not ever try to allocate space on our heap. | 187 // Does not ever try to allocate space on our heap. |
167 kNoAllocate = 1u << 9 | 188 kNoAllocate = 1u << 9 |
168 }; | 189 }; |
169 typedef base::Flags<Flag> Flags; | 190 typedef base::Flags<Flag> Flags; |
170 | 191 |
171 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc, | 192 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc, |
172 const MachineSignature* machine_sig, | |
173 LocationSignature* location_sig, size_t stack_param_count, | 193 LocationSignature* location_sig, size_t stack_param_count, |
174 Operator::Properties properties, | 194 Operator::Properties properties, |
175 RegList callee_saved_registers, | 195 RegList callee_saved_registers, |
176 RegList callee_saved_fp_registers, Flags flags, | 196 RegList callee_saved_fp_registers, Flags flags, |
177 const char* debug_name = "") | 197 const char* debug_name = "") |
178 : kind_(kind), | 198 : kind_(kind), |
179 target_type_(target_type), | 199 target_type_(target_type), |
180 target_loc_(target_loc), | 200 target_loc_(target_loc), |
181 machine_sig_(machine_sig), | |
182 location_sig_(location_sig), | 201 location_sig_(location_sig), |
183 stack_param_count_(stack_param_count), | 202 stack_param_count_(stack_param_count), |
184 properties_(properties), | 203 properties_(properties), |
185 callee_saved_registers_(callee_saved_registers), | 204 callee_saved_registers_(callee_saved_registers), |
186 callee_saved_fp_registers_(callee_saved_fp_registers), | 205 callee_saved_fp_registers_(callee_saved_fp_registers), |
187 flags_(flags), | 206 flags_(flags), |
188 debug_name_(debug_name) { | 207 debug_name_(debug_name) { |
189 DCHECK(machine_sig->return_count() == location_sig->return_count()); | |
190 DCHECK(machine_sig->parameter_count() == location_sig->parameter_count()); | |
191 } | 208 } |
192 | 209 |
193 // Returns the kind of this call. | 210 // Returns the kind of this call. |
194 Kind kind() const { return kind_; } | 211 Kind kind() const { return kind_; } |
195 | 212 |
196 // Returns {true} if this descriptor is a call to a C function. | 213 // Returns {true} if this descriptor is a call to a C function. |
197 bool IsCFunctionCall() const { return kind_ == kCallAddress; } | 214 bool IsCFunctionCall() const { return kind_ == kCallAddress; } |
198 | 215 |
199 // Returns {true} if this descriptor is a call to a JSFunction. | 216 // Returns {true} if this descriptor is a call to a JSFunction. |
200 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; } | 217 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; } |
201 | 218 |
202 bool RequiresFrameAsIncoming() const { | 219 bool RequiresFrameAsIncoming() const { |
203 return IsCFunctionCall() || IsJSFunctionCall(); | 220 return IsCFunctionCall() || IsJSFunctionCall(); |
204 } | 221 } |
205 | 222 |
206 // The number of return values from this call. | 223 // The number of return values from this call. |
207 size_t ReturnCount() const { return machine_sig_->return_count(); } | 224 size_t ReturnCount() const { return location_sig_->return_count(); } |
208 | 225 |
209 // The number of C parameters to this call. | 226 // The number of C parameters to this call. |
210 size_t CParameterCount() const { return machine_sig_->parameter_count(); } | 227 size_t ParameterCount() const { return location_sig_->parameter_count(); } |
211 | 228 |
212 // The number of stack parameters to the call. | 229 // The number of stack parameters to the call. |
213 size_t StackParameterCount() const { return stack_param_count_; } | 230 size_t StackParameterCount() const { return stack_param_count_; } |
214 | 231 |
215 // The number of parameters to the JS function call. | 232 // The number of parameters to the JS function call. |
216 size_t JSParameterCount() const { | 233 size_t JSParameterCount() const { |
217 DCHECK(IsJSFunctionCall()); | 234 DCHECK(IsJSFunctionCall()); |
218 return stack_param_count_; | 235 return stack_param_count_; |
219 } | 236 } |
220 | 237 |
221 // The total number of inputs to this call, which includes the target, | 238 // The total number of inputs to this call, which includes the target, |
222 // receiver, context, etc. | 239 // receiver, context, etc. |
223 // TODO(titzer): this should input the framestate input too. | 240 // TODO(titzer): this should input the framestate input too. |
224 size_t InputCount() const { return 1 + machine_sig_->parameter_count(); } | 241 size_t InputCount() const { return 1 + location_sig_->parameter_count(); } |
225 | 242 |
226 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; } | 243 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; } |
227 | 244 |
228 Flags flags() const { return flags_; } | 245 Flags flags() const { return flags_; } |
229 | 246 |
230 bool NeedsFrameState() const { return flags() & kNeedsFrameState; } | 247 bool NeedsFrameState() const { return flags() & kNeedsFrameState; } |
231 bool SupportsTailCalls() const { return flags() & kSupportsTailCalls; } | 248 bool SupportsTailCalls() const { return flags() & kSupportsTailCalls; } |
232 bool UseNativeStack() const { return flags() & kUseNativeStack; } | 249 bool UseNativeStack() const { return flags() & kUseNativeStack; } |
233 bool InitializeRootRegister() const { | 250 bool InitializeRootRegister() const { |
234 return flags() & kInitializeRootRegister; | 251 return flags() & kInitializeRootRegister; |
235 } | 252 } |
236 | 253 |
237 LinkageLocation GetReturnLocation(size_t index) const { | 254 LinkageLocation GetReturnLocation(size_t index) const { |
238 return location_sig_->GetReturn(index); | 255 return location_sig_->GetReturn(index); |
239 } | 256 } |
240 | 257 |
241 LinkageLocation GetInputLocation(size_t index) const { | 258 LinkageLocation GetInputLocation(size_t index) const { |
242 if (index == 0) return target_loc_; | 259 if (index == 0) return target_loc_; |
243 return location_sig_->GetParam(index - 1); | 260 return location_sig_->GetParam(index - 1); |
244 } | 261 } |
245 | 262 |
246 const MachineSignature* GetMachineSignature() const { return machine_sig_; } | 263 MachineSignature* GetMachineSignature(Zone* zone) const; |
247 | 264 |
248 MachineType GetReturnType(size_t index) const { | 265 MachineType GetReturnType(size_t index) const { |
249 return machine_sig_->GetReturn(index); | 266 return location_sig_->GetReturn(index).GetType(); |
250 } | 267 } |
251 | 268 |
252 MachineType GetInputType(size_t index) const { | 269 MachineType GetInputType(size_t index) const { |
253 if (index == 0) return target_type_; | 270 if (index == 0) return target_type_; |
254 return machine_sig_->GetParam(index - 1); | 271 return location_sig_->GetParam(index - 1).GetType(); |
| 272 } |
| 273 |
| 274 MachineType GetParameterType(size_t index) const { |
| 275 return location_sig_->GetParam(index).GetType(); |
255 } | 276 } |
256 | 277 |
257 // Operator properties describe how this call can be optimized, if at all. | 278 // Operator properties describe how this call can be optimized, if at all. |
258 Operator::Properties properties() const { return properties_; } | 279 Operator::Properties properties() const { return properties_; } |
259 | 280 |
260 // Get the callee-saved registers, if any, across this call. | 281 // Get the callee-saved registers, if any, across this call. |
261 RegList CalleeSavedRegisters() const { return callee_saved_registers_; } | 282 RegList CalleeSavedRegisters() const { return callee_saved_registers_; } |
262 | 283 |
263 // Get the callee-saved FP registers, if any, across this call. | 284 // Get the callee-saved FP registers, if any, across this call. |
264 RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; } | 285 RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; } |
265 | 286 |
266 const char* debug_name() const { return debug_name_; } | 287 const char* debug_name() const { return debug_name_; } |
267 | 288 |
268 bool UsesOnlyRegisters() const; | 289 bool UsesOnlyRegisters() const; |
269 | 290 |
270 bool HasSameReturnLocationsAs(const CallDescriptor* other) const; | 291 bool HasSameReturnLocationsAs(const CallDescriptor* other) const; |
271 | 292 |
272 bool CanTailCall(const Node* call, int* stack_param_delta) const; | 293 bool CanTailCall(const Node* call, int* stack_param_delta) const; |
273 | 294 |
274 private: | 295 private: |
275 friend class Linkage; | 296 friend class Linkage; |
276 | 297 |
277 const Kind kind_; | 298 const Kind kind_; |
278 const MachineType target_type_; | 299 const MachineType target_type_; |
279 const LinkageLocation target_loc_; | 300 const LinkageLocation target_loc_; |
280 const MachineSignature* const machine_sig_; | |
281 const LocationSignature* const location_sig_; | 301 const LocationSignature* const location_sig_; |
282 const size_t stack_param_count_; | 302 const size_t stack_param_count_; |
283 const Operator::Properties properties_; | 303 const Operator::Properties properties_; |
284 const RegList callee_saved_registers_; | 304 const RegList callee_saved_registers_; |
285 const RegList callee_saved_fp_registers_; | 305 const RegList callee_saved_fp_registers_; |
286 const Flags flags_; | 306 const Flags flags_; |
287 const char* const debug_name_; | 307 const char* const debug_name_; |
288 | 308 |
289 DISALLOW_COPY_AND_ASSIGN(CallDescriptor); | 309 DISALLOW_COPY_AND_ASSIGN(CallDescriptor); |
290 }; | 310 }; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 CallDescriptor* const incoming_; | 423 CallDescriptor* const incoming_; |
404 | 424 |
405 DISALLOW_COPY_AND_ASSIGN(Linkage); | 425 DISALLOW_COPY_AND_ASSIGN(Linkage); |
406 }; | 426 }; |
407 | 427 |
408 } // namespace compiler | 428 } // namespace compiler |
409 } // namespace internal | 429 } // namespace internal |
410 } // namespace v8 | 430 } // namespace v8 |
411 | 431 |
412 #endif // V8_COMPILER_LINKAGE_H_ | 432 #endif // V8_COMPILER_LINKAGE_H_ |
OLD | NEW |