deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / linkage-impl.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_IMPL_H_
6 #define V8_COMPILER_LINKAGE_IMPL_H_
7
8 #include "src/code-stubs.h"
9 #include "src/compiler/osr.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14
15 // TODO(titzer): replace uses of int with size_t in LinkageHelper.
16 template <typename LinkageTraits>
17 class LinkageHelper {
18  public:
19   static const RegList kNoCalleeSaved = 0;
20
21   static void AddReturnLocations(LocationSignature::Builder* locations) {
22     DCHECK(locations->return_count_ <= 2);
23     if (locations->return_count_ > 0) {
24       locations->AddReturn(regloc(LinkageTraits::ReturnValueReg()));
25     }
26     if (locations->return_count_ > 1) {
27       locations->AddReturn(regloc(LinkageTraits::ReturnValue2Reg()));
28     }
29   }
30
31   // TODO(turbofan): cache call descriptors for JSFunction calls.
32   static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
33                                              int js_parameter_count,
34                                              CallDescriptor::Flags flags) {
35     const size_t return_count = 1;
36     const size_t context_count = 1;
37     const size_t parameter_count = js_parameter_count + context_count;
38
39     LocationSignature::Builder locations(zone, return_count, parameter_count);
40     MachineSignature::Builder types(zone, return_count, parameter_count);
41
42     // Add returns.
43     AddReturnLocations(&locations);
44     for (size_t i = 0; i < return_count; i++) {
45       types.AddReturn(kMachAnyTagged);
46     }
47
48     // All parameters to JS calls go on the stack.
49     for (int i = 0; i < js_parameter_count; i++) {
50       int spill_slot_index = i - js_parameter_count;
51       locations.AddParam(stackloc(spill_slot_index));
52       types.AddParam(kMachAnyTagged);
53     }
54     // Add context.
55     locations.AddParam(regloc(LinkageTraits::ContextReg()));
56     types.AddParam(kMachAnyTagged);
57
58     // The target for JS function calls is the JSFunction object.
59     MachineType target_type = kMachAnyTagged;
60     // TODO(titzer): When entering into an OSR function from unoptimized code,
61     // the JSFunction is not in a register, but it is on the stack in an
62     // unaddressable spill slot. We hack this in the OSR prologue. Fix.
63     LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg());
64     return new (zone) CallDescriptor(     // --
65         CallDescriptor::kCallJSFunction,  // kind
66         target_type,                      // target MachineType
67         target_loc,                       // target location
68         types.Build(),                    // machine_sig
69         locations.Build(),                // location_sig
70         js_parameter_count,               // js_parameter_count
71         Operator::kNoProperties,          // properties
72         kNoCalleeSaved,                   // callee-saved
73         flags,                            // flags
74         "js-call");
75   }
76
77
78   // TODO(turbofan): cache call descriptors for runtime calls.
79   static CallDescriptor* GetRuntimeCallDescriptor(
80       Zone* zone, Runtime::FunctionId function_id, int js_parameter_count,
81       Operator::Properties properties) {
82     const size_t function_count = 1;
83     const size_t num_args_count = 1;
84     const size_t context_count = 1;
85     const size_t parameter_count = function_count +
86                                    static_cast<size_t>(js_parameter_count) +
87                                    num_args_count + context_count;
88
89     const Runtime::Function* function = Runtime::FunctionForId(function_id);
90     const size_t return_count = static_cast<size_t>(function->result_size);
91
92     LocationSignature::Builder locations(zone, return_count, parameter_count);
93     MachineSignature::Builder types(zone, return_count, parameter_count);
94
95     // Add returns.
96     AddReturnLocations(&locations);
97     for (size_t i = 0; i < return_count; i++) {
98       types.AddReturn(kMachAnyTagged);
99     }
100
101     // All parameters to the runtime call go on the stack.
102     for (int i = 0; i < js_parameter_count; i++) {
103       locations.AddParam(stackloc(i - js_parameter_count));
104       types.AddParam(kMachAnyTagged);
105     }
106     // Add runtime function itself.
107     locations.AddParam(regloc(LinkageTraits::RuntimeCallFunctionReg()));
108     types.AddParam(kMachAnyTagged);
109
110     // Add runtime call argument count.
111     locations.AddParam(regloc(LinkageTraits::RuntimeCallArgCountReg()));
112     types.AddParam(kMachPtr);
113
114     // Add context.
115     locations.AddParam(regloc(LinkageTraits::ContextReg()));
116     types.AddParam(kMachAnyTagged);
117
118     CallDescriptor::Flags flags = Linkage::NeedsFrameState(function_id)
119                                       ? CallDescriptor::kNeedsFrameState
120                                       : CallDescriptor::kNoFlags;
121
122     // The target for runtime calls is a code object.
123     MachineType target_type = kMachAnyTagged;
124     LinkageLocation target_loc = LinkageLocation::AnyRegister();
125     return new (zone) CallDescriptor(     // --
126         CallDescriptor::kCallCodeObject,  // kind
127         target_type,                      // target MachineType
128         target_loc,                       // target location
129         types.Build(),                    // machine_sig
130         locations.Build(),                // location_sig
131         js_parameter_count,               // js_parameter_count
132         properties,                       // properties
133         kNoCalleeSaved,                   // callee-saved
134         flags,                            // flags
135         function->name);                  // debug name
136   }
137
138
139   // TODO(all): Add support for return representations/locations to
140   // CallInterfaceDescriptor.
141   // TODO(turbofan): cache call descriptors for code stub calls.
142   static CallDescriptor* GetStubCallDescriptor(
143       Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
144       int stack_parameter_count, CallDescriptor::Flags flags,
145       Operator::Properties properties, MachineType return_type) {
146     const int register_parameter_count =
147         descriptor.GetEnvironmentParameterCount();
148     const int js_parameter_count =
149         register_parameter_count + stack_parameter_count;
150     const int context_count = 1;
151     const size_t return_count = 1;
152     const size_t parameter_count =
153         static_cast<size_t>(js_parameter_count + context_count);
154
155     LocationSignature::Builder locations(zone, return_count, parameter_count);
156     MachineSignature::Builder types(zone, return_count, parameter_count);
157
158     // Add return location.
159     AddReturnLocations(&locations);
160     types.AddReturn(return_type);
161
162     // Add parameters in registers and on the stack.
163     for (int i = 0; i < js_parameter_count; i++) {
164       if (i < register_parameter_count) {
165         // The first parameters go in registers.
166         Register reg = descriptor.GetEnvironmentParameterRegister(i);
167         Representation rep =
168             descriptor.GetEnvironmentParameterRepresentation(i);
169         locations.AddParam(regloc(reg));
170         types.AddParam(reptyp(rep));
171       } else {
172         // The rest of the parameters go on the stack.
173         int stack_slot = i - register_parameter_count - stack_parameter_count;
174         locations.AddParam(stackloc(stack_slot));
175         types.AddParam(kMachAnyTagged);
176       }
177     }
178     // Add context.
179     locations.AddParam(regloc(LinkageTraits::ContextReg()));
180     types.AddParam(kMachAnyTagged);
181
182     // The target for stub calls is a code object.
183     MachineType target_type = kMachAnyTagged;
184     LinkageLocation target_loc = LinkageLocation::AnyRegister();
185     return new (zone) CallDescriptor(     // --
186         CallDescriptor::kCallCodeObject,  // kind
187         target_type,                      // target MachineType
188         target_loc,                       // target location
189         types.Build(),                    // machine_sig
190         locations.Build(),                // location_sig
191         js_parameter_count,               // js_parameter_count
192         properties,                       // properties
193         kNoCalleeSaved,                   // callee-saved registers
194         flags,                            // flags
195         descriptor.DebugName(isolate));
196   }
197
198   static CallDescriptor* GetSimplifiedCDescriptor(
199       Zone* zone, const MachineSignature* msig) {
200     LocationSignature::Builder locations(zone, msig->return_count(),
201                                          msig->parameter_count());
202     // Add return location(s).
203     AddReturnLocations(&locations);
204
205     // Add register and/or stack parameter(s).
206     const int parameter_count = static_cast<int>(msig->parameter_count());
207     for (int i = 0; i < parameter_count; i++) {
208       if (i < LinkageTraits::CRegisterParametersLength()) {
209         locations.AddParam(regloc(LinkageTraits::CRegisterParameter(i)));
210       } else {
211         locations.AddParam(stackloc(-1 - i));
212       }
213     }
214
215     // The target for C calls is always an address (i.e. machine pointer).
216     MachineType target_type = kMachPtr;
217     LinkageLocation target_loc = LinkageLocation::AnyRegister();
218     return new (zone) CallDescriptor(  // --
219         CallDescriptor::kCallAddress,  // kind
220         target_type,                   // target MachineType
221         target_loc,                    // target location
222         msig,                          // machine_sig
223         locations.Build(),             // location_sig
224         0,                             // js_parameter_count
225         Operator::kNoProperties,       // properties
226         LinkageTraits::CCalleeSaveRegisters(), CallDescriptor::kNoFlags,
227         "c-call");
228   }
229
230   static LinkageLocation regloc(Register reg) {
231     return LinkageLocation(Register::ToAllocationIndex(reg));
232   }
233
234   static LinkageLocation stackloc(int i) {
235     DCHECK_LT(i, 0);
236     return LinkageLocation(i);
237   }
238
239   static MachineType reptyp(Representation representation) {
240     switch (representation.kind()) {
241       case Representation::kInteger8:
242         return kMachInt8;
243       case Representation::kUInteger8:
244         return kMachUint8;
245       case Representation::kInteger16:
246         return kMachInt16;
247       case Representation::kUInteger16:
248         return kMachUint16;
249       case Representation::kInteger32:
250         return kMachInt32;
251       case Representation::kSmi:
252       case Representation::kTagged:
253       case Representation::kHeapObject:
254         return kMachAnyTagged;
255       case Representation::kDouble:
256         return kMachFloat64;
257       case Representation::kExternal:
258         return kMachPtr;
259       case Representation::kNone:
260       case Representation::kNumRepresentations:
261         break;
262     }
263     UNREACHABLE();
264     return kMachNone;
265   }
266 };
267
268
269 LinkageLocation Linkage::GetOsrValueLocation(int index) const {
270   CHECK(incoming_->IsJSFunctionCall());
271   int parameter_count = static_cast<int>(incoming_->JSParameterCount() - 1);
272   int first_stack_slot = OsrHelper::FirstStackSlotIndex(parameter_count);
273
274   if (index >= first_stack_slot) {
275     // Local variable stored in this (callee) stack.
276     int spill_index =
277         LinkageLocation::ANY_REGISTER + 1 + index - first_stack_slot;
278     // TODO(titzer): bailout instead of crashing here.
279     CHECK(spill_index <= LinkageLocation::MAX_STACK_SLOT);
280     return LinkageLocation(spill_index);
281   } else {
282     // Parameter. Use the assigned location from the incoming call descriptor.
283     int parameter_index = 1 + index;  // skip index 0, which is the target.
284     return incoming_->GetInputLocation(parameter_index);
285   }
286 }
287
288 }  // namespace compiler
289 }  // namespace internal
290 }  // namespace v8
291
292 #endif  // V8_COMPILER_LINKAGE_IMPL_H_