OLD | NEW |
| (Empty) |
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, // stack_parameter_count | |
71 Operator::kNoProperties, // properties | |
72 kNoCalleeSaved, // callee-saved | |
73 kNoCalleeSaved, // callee-saved fp | |
74 flags, // flags | |
75 "js-call"); | |
76 } | |
77 | |
78 | |
79 // TODO(turbofan): cache call descriptors for runtime calls. | |
80 static CallDescriptor* GetRuntimeCallDescriptor( | |
81 Zone* zone, Runtime::FunctionId function_id, int js_parameter_count, | |
82 Operator::Properties properties) { | |
83 const size_t function_count = 1; | |
84 const size_t num_args_count = 1; | |
85 const size_t context_count = 1; | |
86 const size_t parameter_count = function_count + | |
87 static_cast<size_t>(js_parameter_count) + | |
88 num_args_count + context_count; | |
89 | |
90 const Runtime::Function* function = Runtime::FunctionForId(function_id); | |
91 const size_t return_count = static_cast<size_t>(function->result_size); | |
92 | |
93 LocationSignature::Builder locations(zone, return_count, parameter_count); | |
94 MachineSignature::Builder types(zone, return_count, parameter_count); | |
95 | |
96 // Add returns. | |
97 AddReturnLocations(&locations); | |
98 for (size_t i = 0; i < return_count; i++) { | |
99 types.AddReturn(kMachAnyTagged); | |
100 } | |
101 | |
102 // All parameters to the runtime call go on the stack. | |
103 for (int i = 0; i < js_parameter_count; i++) { | |
104 locations.AddParam(stackloc(i - js_parameter_count)); | |
105 types.AddParam(kMachAnyTagged); | |
106 } | |
107 // Add runtime function itself. | |
108 locations.AddParam(regloc(LinkageTraits::RuntimeCallFunctionReg())); | |
109 types.AddParam(kMachAnyTagged); | |
110 | |
111 // Add runtime call argument count. | |
112 locations.AddParam(regloc(LinkageTraits::RuntimeCallArgCountReg())); | |
113 types.AddParam(kMachPtr); | |
114 | |
115 // Add context. | |
116 locations.AddParam(regloc(LinkageTraits::ContextReg())); | |
117 types.AddParam(kMachAnyTagged); | |
118 | |
119 CallDescriptor::Flags flags = Linkage::FrameStateInputCount(function_id) > 0 | |
120 ? CallDescriptor::kNeedsFrameState | |
121 : CallDescriptor::kNoFlags; | |
122 | |
123 // The target for runtime calls is a code object. | |
124 MachineType target_type = kMachAnyTagged; | |
125 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); | |
126 return new (zone) CallDescriptor( // -- | |
127 CallDescriptor::kCallCodeObject, // kind | |
128 target_type, // target MachineType | |
129 target_loc, // target location | |
130 types.Build(), // machine_sig | |
131 locations.Build(), // location_sig | |
132 js_parameter_count, // stack_parameter_count | |
133 properties, // properties | |
134 kNoCalleeSaved, // callee-saved | |
135 kNoCalleeSaved, // callee-saved fp | |
136 flags, // flags | |
137 function->name); // debug name | |
138 } | |
139 | |
140 | |
141 // TODO(all): Add support for return representations/locations to | |
142 // CallInterfaceDescriptor. | |
143 // TODO(turbofan): cache call descriptors for code stub calls. | |
144 static CallDescriptor* GetStubCallDescriptor( | |
145 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor, | |
146 int stack_parameter_count, CallDescriptor::Flags flags, | |
147 Operator::Properties properties, MachineType return_type) { | |
148 const int register_parameter_count = descriptor.GetRegisterParameterCount(); | |
149 const int js_parameter_count = | |
150 register_parameter_count + stack_parameter_count; | |
151 const int context_count = 1; | |
152 const size_t return_count = 1; | |
153 const size_t parameter_count = | |
154 static_cast<size_t>(js_parameter_count + context_count); | |
155 | |
156 LocationSignature::Builder locations(zone, return_count, parameter_count); | |
157 MachineSignature::Builder types(zone, return_count, parameter_count); | |
158 | |
159 // Add return location. | |
160 AddReturnLocations(&locations); | |
161 types.AddReturn(return_type); | |
162 | |
163 // Add parameters in registers and on the stack. | |
164 for (int i = 0; i < js_parameter_count; i++) { | |
165 if (i < register_parameter_count) { | |
166 // The first parameters go in registers. | |
167 Register reg = descriptor.GetRegisterParameter(i); | |
168 Representation rep = | |
169 RepresentationFromType(descriptor.GetParameterType(i)); | |
170 locations.AddParam(regloc(reg)); | |
171 types.AddParam(reptyp(rep)); | |
172 } else { | |
173 // The rest of the parameters go on the stack. | |
174 int stack_slot = i - register_parameter_count - stack_parameter_count; | |
175 locations.AddParam(stackloc(stack_slot)); | |
176 types.AddParam(kMachAnyTagged); | |
177 } | |
178 } | |
179 // Add context. | |
180 locations.AddParam(regloc(LinkageTraits::ContextReg())); | |
181 types.AddParam(kMachAnyTagged); | |
182 | |
183 // The target for stub calls is a code object. | |
184 MachineType target_type = kMachAnyTagged; | |
185 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); | |
186 return new (zone) CallDescriptor( // -- | |
187 CallDescriptor::kCallCodeObject, // kind | |
188 target_type, // target MachineType | |
189 target_loc, // target location | |
190 types.Build(), // machine_sig | |
191 locations.Build(), // location_sig | |
192 stack_parameter_count, // stack_parameter_count | |
193 properties, // properties | |
194 kNoCalleeSaved, // callee-saved registers | |
195 kNoCalleeSaved, // callee-saved fp | |
196 flags, // flags | |
197 descriptor.DebugName(isolate)); | |
198 } | |
199 | |
200 static CallDescriptor* GetInterpreterDispatchDescriptor(Zone* zone) { | |
201 MachineSignature::Builder types(zone, 0, 3); | |
202 LocationSignature::Builder locations(zone, 0, 3); | |
203 | |
204 // Add registers for fixed parameters passed via interpreter dispatch. | |
205 STATIC_ASSERT(0 == Linkage::kInterpreterBytecodeOffsetParameter); | |
206 types.AddParam(kMachIntPtr); | |
207 locations.AddParam(regloc(LinkageTraits::InterpreterBytecodeOffsetReg())); | |
208 | |
209 STATIC_ASSERT(1 == Linkage::kInterpreterBytecodeArrayParameter); | |
210 types.AddParam(kMachAnyTagged); | |
211 locations.AddParam(regloc(LinkageTraits::InterpreterBytecodeArrayReg())); | |
212 | |
213 STATIC_ASSERT(2 == Linkage::kInterpreterDispatchTableParameter); | |
214 types.AddParam(kMachPtr); | |
215 locations.AddParam(regloc(LinkageTraits::InterpreterDispatchTableReg())); | |
216 | |
217 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); | |
218 return new (zone) CallDescriptor( // -- | |
219 CallDescriptor::kInterpreterDispatch, // kind | |
220 kMachNone, // target MachineType | |
221 target_loc, // target location | |
222 types.Build(), // machine_sig | |
223 locations.Build(), // location_sig | |
224 0, // stack_parameter_count | |
225 Operator::kNoProperties, // properties | |
226 kNoCalleeSaved, // callee-saved registers | |
227 kNoCalleeSaved, // callee-saved fp regs | |
228 CallDescriptor::kSupportsTailCalls, // flags | |
229 "interpreter-dispatch"); | |
230 } | |
231 | |
232 static LinkageLocation regloc(Register reg) { | |
233 return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg)); | |
234 } | |
235 | |
236 static LinkageLocation stackloc(int i) { | |
237 return LinkageLocation::ForCallerFrameSlot(i); | |
238 } | |
239 | |
240 static MachineType reptyp(Representation representation) { | |
241 switch (representation.kind()) { | |
242 case Representation::kInteger8: | |
243 return kMachInt8; | |
244 case Representation::kUInteger8: | |
245 return kMachUint8; | |
246 case Representation::kInteger16: | |
247 return kMachInt16; | |
248 case Representation::kUInteger16: | |
249 return kMachUint16; | |
250 case Representation::kInteger32: | |
251 return kMachInt32; | |
252 case Representation::kSmi: | |
253 case Representation::kTagged: | |
254 case Representation::kHeapObject: | |
255 return kMachAnyTagged; | |
256 case Representation::kDouble: | |
257 return kMachFloat64; | |
258 case Representation::kExternal: | |
259 return kMachPtr; | |
260 case Representation::kNone: | |
261 case Representation::kNumRepresentations: | |
262 break; | |
263 } | |
264 UNREACHABLE(); | |
265 return kMachNone; | |
266 } | |
267 }; | |
268 | |
269 | |
270 LinkageLocation Linkage::GetOsrValueLocation(int index) const { | |
271 CHECK(incoming_->IsJSFunctionCall()); | |
272 int parameter_count = static_cast<int>(incoming_->JSParameterCount() - 1); | |
273 int first_stack_slot = OsrHelper::FirstStackSlotIndex(parameter_count); | |
274 | |
275 if (index == kOsrContextSpillSlotIndex) { | |
276 // Context. Use the parameter location of the context spill slot. | |
277 // Parameter (arity + 1) is special for the context of the function frame. | |
278 int context_index = 1 + 1 + parameter_count; // target + receiver + params | |
279 return incoming_->GetInputLocation(context_index); | |
280 } else if (index >= first_stack_slot) { | |
281 // Local variable stored in this (callee) stack. | |
282 int spill_index = index - first_stack_slot; | |
283 return LinkageLocation::ForCalleeFrameSlot(spill_index); | |
284 } else { | |
285 // Parameter. Use the assigned location from the incoming call descriptor. | |
286 int parameter_index = 1 + index; // skip index 0, which is the target. | |
287 return incoming_->GetInputLocation(parameter_index); | |
288 } | |
289 } | |
290 | |
291 } // namespace compiler | |
292 } // namespace internal | |
293 } // namespace v8 | |
294 | |
295 #endif // V8_COMPILER_LINKAGE_IMPL_H_ | |
OLD | NEW |