blob: 252f0443213e522875697d8013649d58a02977a0 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/frame.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/frames.h"
12#include "src/machine-type.h"
13#include "src/runtime/runtime.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/zone.h"
15
16namespace v8 {
17namespace internal {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018
19class CallInterfaceDescriptor;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020class CompilationInfo;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022namespace compiler {
23
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024const RegList kNoCalleeSaved = 0;
25
26class Node;
27class OsrHelper;
28
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029// Describes the location for a parameter or a return value to a call.
30class LinkageLocation {
31 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 bool operator==(const LinkageLocation& other) const {
33 return bit_field_ == other.bit_field_;
34 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 bool operator!=(const LinkageLocation& other) const {
37 return !(*this == other);
38 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 static LinkageLocation ForAnyRegister() {
41 return LinkageLocation(REGISTER, ANY_REGISTER);
42 }
43
44 static LinkageLocation ForRegister(int32_t reg) {
45 DCHECK(reg >= 0);
46 return LinkageLocation(REGISTER, reg);
47 }
48
49 static LinkageLocation ForCallerFrameSlot(int32_t slot) {
50 DCHECK(slot < 0);
51 return LinkageLocation(STACK_SLOT, slot);
52 }
53
54 static LinkageLocation ForCalleeFrameSlot(int32_t slot) {
55 // TODO(titzer): bailout instead of crashing here.
56 DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT);
57 return LinkageLocation(STACK_SLOT, slot);
58 }
59
60 static LinkageLocation ForSavedCallerReturnAddress() {
61 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
62 StandardFrameConstants::kCallerPCOffset) /
63 kPointerSize);
64 }
65
66 static LinkageLocation ForSavedCallerFramePtr() {
67 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
68 StandardFrameConstants::kCallerFPOffset) /
69 kPointerSize);
70 }
71
72 static LinkageLocation ForSavedCallerConstantPool() {
73 DCHECK(V8_EMBEDDED_CONSTANT_POOL);
74 return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
75 StandardFrameConstants::kConstantPoolOffset) /
76 kPointerSize);
77 }
78
79 static LinkageLocation ConvertToTailCallerLocation(
80 LinkageLocation caller_location, int stack_param_delta) {
81 if (!caller_location.IsRegister()) {
82 return LinkageLocation(STACK_SLOT,
83 caller_location.GetLocation() - stack_param_delta);
84 }
85 return caller_location;
86 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087
88 private:
89 friend class CallDescriptor;
90 friend class OperandGenerator;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091
92 enum LocationType { REGISTER, STACK_SLOT };
93
94 class TypeField : public BitField<LocationType, 0, 1> {};
95 class LocationField : public BitField<int32_t, TypeField::kNext, 31> {};
96
97 static const int32_t ANY_REGISTER = -1;
98 static const int32_t MAX_STACK_SLOT = 32767;
99
100 LinkageLocation(LocationType type, int32_t location) {
101 bit_field_ = TypeField::encode(type) |
102 ((location << LocationField::kShift) & LocationField::kMask);
103 }
104
105 int32_t GetLocation() const {
106 return static_cast<int32_t>(bit_field_ & LocationField::kMask) >>
107 LocationField::kShift;
108 }
109
110 bool IsRegister() const { return TypeField::decode(bit_field_) == REGISTER; }
111 bool IsAnyRegister() const {
112 return IsRegister() && GetLocation() == ANY_REGISTER;
113 }
114 bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; }
115 bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; }
116
117 int32_t AsRegister() const {
118 DCHECK(IsRegister());
119 return GetLocation();
120 }
121 int32_t AsCallerFrameSlot() const {
122 DCHECK(IsCallerFrameSlot());
123 return GetLocation();
124 }
125 int32_t AsCalleeFrameSlot() const {
126 DCHECK(IsCalleeFrameSlot());
127 return GetLocation();
128 }
129
130 int32_t bit_field_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131};
132
133typedef Signature<LinkageLocation> LocationSignature;
134
135// Describes a call to various parts of the compiler. Every call has the notion
136// of a "target", which is the first input to the call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137class CallDescriptor final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 public:
139 // Describes the kind of this call, which determines the target.
140 enum Kind {
141 kCallCodeObject, // target is a Code object
142 kCallJSFunction, // target is a JSFunction object
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 kCallAddress, // target is a machine pointer
144 kLazyBailout // the call is no-op, only used for lazy bailout
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 };
146
147 enum Flag {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 kNoFlags = 0u,
149 kNeedsFrameState = 1u << 0,
150 kPatchableCallSite = 1u << 1,
151 kNeedsNopAfterCall = 1u << 2,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 kHasExceptionHandler = 1u << 3,
153 kHasLocalCatchHandler = 1u << 4,
154 kSupportsTailCalls = 1u << 5,
155 kCanUseRoots = 1u << 6,
156 // Indicates that the native stack should be used for a code object. This
157 // information is important for native calls on arm64.
158 kUseNativeStack = 1u << 7,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000159 kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall
160 };
161 typedef base::Flags<Flag> Flags;
162
163 CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 const MachineSignature* machine_sig,
165 LocationSignature* location_sig, size_t stack_param_count,
166 Operator::Properties properties,
167 RegList callee_saved_registers,
168 RegList callee_saved_fp_registers, Flags flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 const char* debug_name = "")
170 : kind_(kind),
171 target_type_(target_type),
172 target_loc_(target_loc),
173 machine_sig_(machine_sig),
174 location_sig_(location_sig),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 stack_param_count_(stack_param_count),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 properties_(properties),
177 callee_saved_registers_(callee_saved_registers),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 callee_saved_fp_registers_(callee_saved_fp_registers),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 flags_(flags),
180 debug_name_(debug_name) {
181 DCHECK(machine_sig->return_count() == location_sig->return_count());
182 DCHECK(machine_sig->parameter_count() == location_sig->parameter_count());
183 }
184
185 // Returns the kind of this call.
186 Kind kind() const { return kind_; }
187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 // Returns {true} if this descriptor is a call to a C function.
189 bool IsCFunctionCall() const { return kind_ == kCallAddress; }
190
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 // Returns {true} if this descriptor is a call to a JSFunction.
192 bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 bool RequiresFrameAsIncoming() const {
195 return IsCFunctionCall() || IsJSFunctionCall();
196 }
197
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 // The number of return values from this call.
199 size_t ReturnCount() const { return machine_sig_->return_count(); }
200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 // The number of C parameters to this call.
202 size_t CParameterCount() const { return machine_sig_->parameter_count(); }
203
204 // The number of stack parameters to the call.
205 size_t StackParameterCount() const { return stack_param_count_; }
206
207 // The number of parameters to the JS function call.
208 size_t JSParameterCount() const {
209 DCHECK(IsJSFunctionCall());
210 return stack_param_count_;
211 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212
213 // The total number of inputs to this call, which includes the target,
214 // receiver, context, etc.
215 // TODO(titzer): this should input the framestate input too.
216 size_t InputCount() const { return 1 + machine_sig_->parameter_count(); }
217
218 size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
219
220 Flags flags() const { return flags_; }
221
222 bool NeedsFrameState() const { return flags() & kNeedsFrameState; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 bool SupportsTailCalls() const { return flags() & kSupportsTailCalls; }
224 bool UseNativeStack() const { return flags() & kUseNativeStack; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225
226 LinkageLocation GetReturnLocation(size_t index) const {
227 return location_sig_->GetReturn(index);
228 }
229
230 LinkageLocation GetInputLocation(size_t index) const {
231 if (index == 0) return target_loc_;
232 return location_sig_->GetParam(index - 1);
233 }
234
235 const MachineSignature* GetMachineSignature() const { return machine_sig_; }
236
237 MachineType GetReturnType(size_t index) const {
238 return machine_sig_->GetReturn(index);
239 }
240
241 MachineType GetInputType(size_t index) const {
242 if (index == 0) return target_type_;
243 return machine_sig_->GetParam(index - 1);
244 }
245
246 // Operator properties describe how this call can be optimized, if at all.
247 Operator::Properties properties() const { return properties_; }
248
249 // Get the callee-saved registers, if any, across this call.
250 RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
251
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 // Get the callee-saved FP registers, if any, across this call.
253 RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
254
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 const char* debug_name() const { return debug_name_; }
256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257 bool UsesOnlyRegisters() const;
258
259 bool HasSameReturnLocationsAs(const CallDescriptor* other) const;
260
261 bool CanTailCall(const Node* call, int* stack_param_delta) const;
262
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 private:
264 friend class Linkage;
265
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400266 const Kind kind_;
267 const MachineType target_type_;
268 const LinkageLocation target_loc_;
269 const MachineSignature* const machine_sig_;
270 const LocationSignature* const location_sig_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 const size_t stack_param_count_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272 const Operator::Properties properties_;
273 const RegList callee_saved_registers_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 const RegList callee_saved_fp_registers_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 const Flags flags_;
276 const char* const debug_name_;
277
278 DISALLOW_COPY_AND_ASSIGN(CallDescriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279};
280
281DEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags)
282
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400283std::ostream& operator<<(std::ostream& os, const CallDescriptor& d);
284std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285
286// Defines the linkage for a compilation, including the calling conventions
287// for incoming parameters and return value(s) as well as the outgoing calling
288// convention for any kind of call. Linkage is generally architecture-specific.
289//
290// Can be used to translate {arg_index} (i.e. index of the call node input) as
291// well as {param_index} (i.e. as stored in parameter nodes) into an operator
292// representing the architecture-specific location. The following call node
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293// layouts are supported (where {n} is the number of value inputs):
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294//
295// #0 #1 #2 #3 [...] #n
296// Call[CodeStub] code, arg 1, arg 2, arg 3, [...], context
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297// Call[JSFunction] function, rcvr, arg 1, arg 2, [...], new, #arg, context
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298// Call[Runtime] CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
299class Linkage : public ZoneObject {
300 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400302
303 static CallDescriptor* ComputeIncoming(Zone* zone, CompilationInfo* info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304
305 // The call descriptor for this compilation unit describes the locations
306 // of incoming parameters and the outgoing return value(s).
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400307 CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
309 int parameter_count,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400310 CallDescriptor::Flags flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 static CallDescriptor* GetRuntimeCallDescriptor(
313 Zone* zone, Runtime::FunctionId function, int parameter_count,
314 Operator::Properties properties, CallDescriptor::Flags flags);
315
316 static CallDescriptor* GetLazyBailoutDescriptor(Zone* zone);
317
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 static CallDescriptor* GetStubCallDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
320 int stack_parameter_count, CallDescriptor::Flags flags,
321 Operator::Properties properties = Operator::kNoProperties,
322 MachineType return_type = MachineType::AnyTagged(),
323 size_t return_count = 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324
325 // Creates a call descriptor for simplified C calls that is appropriate
326 // for the host platform. This simplified calling convention only supports
327 // integers and pointers of one word size each, i.e. no floating point,
328 // structs, pointers to members, etc.
329 static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 const MachineSignature* sig);
331
332 // Creates a call descriptor for interpreter handler code stubs. These are not
333 // intended to be called directly but are instead dispatched to by the
334 // interpreter.
335 static CallDescriptor* GetInterpreterDispatchDescriptor(Zone* zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336
337 // Get the location of an (incoming) parameter to this function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400338 LinkageLocation GetParameterLocation(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 return incoming_->GetInputLocation(index + 1); // + 1 to skip target.
340 }
341
342 // Get the machine type of an (incoming) parameter to this function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400343 MachineType GetParameterType(int index) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 return incoming_->GetInputType(index + 1); // + 1 to skip target.
345 }
346
347 // Get the location where this function should place its return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348 LinkageLocation GetReturnLocation(size_t index = 0) const {
349 return incoming_->GetReturnLocation(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 }
351
352 // Get the machine type of this function's return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 MachineType GetReturnType(size_t index = 0) const {
354 return incoming_->GetReturnType(index);
355 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 bool ParameterHasSecondaryLocation(int index) const;
358 LinkageLocation GetParameterSecondaryLocation(int index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 static int FrameStateInputCount(Runtime::FunctionId function);
361
362 // Get the location where an incoming OSR value is stored.
363 LinkageLocation GetOsrValueLocation(int index) const;
364
365 // A special {Parameter} index for JSCalls that represents the new target.
366 static int GetJSCallNewTargetParamIndex(int parameter_count) {
367 return parameter_count + 0; // Parameter (arity + 0) is special.
368 }
369
370 // A special {Parameter} index for JSCalls that represents the argument count.
371 static int GetJSCallArgCountParamIndex(int parameter_count) {
372 return parameter_count + 1; // Parameter (arity + 1) is special.
373 }
374
375 // A special {Parameter} index for JSCalls that represents the context.
376 static int GetJSCallContextParamIndex(int parameter_count) {
377 return parameter_count + 2; // Parameter (arity + 2) is special.
378 }
379
380 // A special {Parameter} index for JSCalls that represents the closure.
381 static const int kJSCallClosureParamIndex = -1;
382
383 // A special {OsrValue} index to indicate the context spill slot.
384 static const int kOsrContextSpillSlotIndex = -1;
385
386 // Special parameter indices used to pass fixed register data through
387 // interpreter dispatches.
388 static const int kInterpreterAccumulatorParameter = 0;
389 static const int kInterpreterRegisterFileParameter = 1;
390 static const int kInterpreterBytecodeOffsetParameter = 2;
391 static const int kInterpreterBytecodeArrayParameter = 3;
392 static const int kInterpreterDispatchTableParameter = 4;
393 static const int kInterpreterContextParameter = 5;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394
395 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400396 CallDescriptor* const incoming_;
397
398 DISALLOW_COPY_AND_ASSIGN(Linkage);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399};
400
401} // namespace compiler
402} // namespace internal
403} // namespace v8
404
405#endif // V8_COMPILER_LINKAGE_H_