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