|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef jit_VMFunctions_h |
|
8 #define jit_VMFunctions_h |
|
9 |
|
10 #include "jspubtd.h" |
|
11 |
|
12 #include "jit/CompileInfo.h" |
|
13 #include "jit/IonFrames.h" |
|
14 |
|
15 namespace js { |
|
16 |
|
17 class DeclEnvObject; |
|
18 class ForkJoinContext; |
|
19 class StaticWithObject; |
|
20 |
|
21 namespace jit { |
|
22 |
|
23 enum DataType { |
|
24 Type_Void, |
|
25 Type_Bool, |
|
26 Type_Int32, |
|
27 Type_Double, |
|
28 Type_Pointer, |
|
29 Type_Object, |
|
30 Type_Value, |
|
31 Type_Handle |
|
32 }; |
|
33 |
|
34 struct PopValues |
|
35 { |
|
36 uint32_t numValues; |
|
37 |
|
38 explicit PopValues(uint32_t numValues) |
|
39 : numValues(numValues) |
|
40 { } |
|
41 }; |
|
42 |
|
43 // Contains information about a virtual machine function that can be called |
|
44 // from JIT code. Functions described in this manner must conform to a simple |
|
45 // protocol: the return type must have a special "failure" value (for example, |
|
46 // false for bool, or nullptr for Objects). If the function is designed to |
|
47 // return a value that does not meet this requirement - such as |
|
48 // object-or-nullptr, or an integer, an optional, final outParam can be |
|
49 // specified. In this case, the return type must be boolean to indicate |
|
50 // failure. |
|
51 // |
|
52 // All functions described by VMFunction take a JSContext * as a first |
|
53 // argument, and are treated as re-entrant into the VM and therefore fallible. |
|
54 struct VMFunction |
|
55 { |
|
56 // Global linked list of all VMFunctions. |
|
57 static VMFunction *functions; |
|
58 VMFunction *next; |
|
59 |
|
60 // Address of the C function. |
|
61 void *wrapped; |
|
62 |
|
63 // Number of arguments expected, excluding JSContext * as an implicit |
|
64 // first argument and an outparam as a possible implicit final argument. |
|
65 uint32_t explicitArgs; |
|
66 |
|
67 enum ArgProperties { |
|
68 WordByValue = 0, |
|
69 DoubleByValue = 1, |
|
70 WordByRef = 2, |
|
71 DoubleByRef = 3, |
|
72 // BitMask version. |
|
73 Word = 0, |
|
74 Double = 1, |
|
75 ByRef = 2 |
|
76 }; |
|
77 |
|
78 // Contains properties about the first 16 arguments. |
|
79 uint32_t argumentProperties; |
|
80 |
|
81 // Which arguments should be passed in float register on platforms that |
|
82 // have them. |
|
83 uint32_t argumentPassedInFloatRegs; |
|
84 |
|
85 // The outparam may be any Type_*, and must be the final argument to the |
|
86 // function, if not Void. outParam != Void implies that the return type |
|
87 // has a boolean failure mode. |
|
88 DataType outParam; |
|
89 |
|
90 // Type returned by the C function and used by the VMFunction wrapper to |
|
91 // check for failures of the C function. Valid failure/return types are |
|
92 // boolean and object pointers which are asserted inside the VMFunction |
|
93 // constructor. If the C function use an outparam (!= Type_Void), then |
|
94 // the only valid failure/return type is boolean -- object pointers are |
|
95 // pointless because the wrapper will only use it to compare it against |
|
96 // nullptr before discarding its value. |
|
97 DataType returnType; |
|
98 |
|
99 // Note: a maximum of seven root types is supported. |
|
100 enum RootType { |
|
101 RootNone = 0, |
|
102 RootObject, |
|
103 RootString, |
|
104 RootPropertyName, |
|
105 RootFunction, |
|
106 RootValue, |
|
107 RootCell |
|
108 }; |
|
109 |
|
110 // Contains an combination of enumerated types used by the gc for marking |
|
111 // arguments of the VM wrapper. |
|
112 uint64_t argumentRootTypes; |
|
113 |
|
114 // The root type of the out param if outParam == Type_Handle. |
|
115 RootType outParamRootType; |
|
116 |
|
117 // Does this function take a ForkJoinContext * or a JSContext *? |
|
118 ExecutionMode executionMode; |
|
119 |
|
120 // Number of Values the VM wrapper should pop from the stack when it returns. |
|
121 // Used by baseline IC stubs so that they can use tail calls to call the VM |
|
122 // wrapper. |
|
123 uint32_t extraValuesToPop; |
|
124 |
|
125 uint32_t argc() const { |
|
126 // JSContext * + args + (OutParam? *) |
|
127 return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1); |
|
128 } |
|
129 |
|
130 DataType failType() const { |
|
131 return returnType; |
|
132 } |
|
133 |
|
134 ArgProperties argProperties(uint32_t explicitArg) const { |
|
135 return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3); |
|
136 } |
|
137 |
|
138 RootType argRootType(uint32_t explicitArg) const { |
|
139 return RootType((argumentRootTypes >> (3 * explicitArg)) & 7); |
|
140 } |
|
141 |
|
142 bool argPassedInFloatReg(uint32_t explicitArg) const { |
|
143 return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1; |
|
144 } |
|
145 |
|
146 // Return the stack size consumed by explicit arguments. |
|
147 size_t explicitStackSlots() const { |
|
148 size_t stackSlots = explicitArgs; |
|
149 |
|
150 // Fetch all double-word flags of explicit arguments. |
|
151 uint32_t n = |
|
152 ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. |
|
153 & 0x55555555 // = Mask double-size args. |
|
154 & argumentProperties; |
|
155 |
|
156 // Add the number of double-word flags. (expect a few loop |
|
157 // iteration) |
|
158 while (n) { |
|
159 stackSlots++; |
|
160 n &= n - 1; |
|
161 } |
|
162 return stackSlots; |
|
163 } |
|
164 |
|
165 // Double-size argument which are passed by value are taking the space |
|
166 // of 2 C arguments. This function is used to compute the number of |
|
167 // argument expected by the C function. This is not the same as |
|
168 // explicitStackSlots because reference to stack slots may take one less |
|
169 // register in the total count. |
|
170 size_t explicitArgc() const { |
|
171 size_t stackSlots = explicitArgs; |
|
172 |
|
173 // Fetch all explicit arguments. |
|
174 uint32_t n = |
|
175 ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. |
|
176 & argumentProperties; |
|
177 |
|
178 // Filter double-size arguments (0x5 = 0b0101) and remove (& ~) |
|
179 // arguments passed by reference (0b1010 >> 1 == 0b0101). |
|
180 n = (n & 0x55555555) & ~(n >> 1); |
|
181 |
|
182 // Add the number of double-word transfered by value. (expect a few |
|
183 // loop iteration) |
|
184 while (n) { |
|
185 stackSlots++; |
|
186 n &= n - 1; |
|
187 } |
|
188 return stackSlots; |
|
189 } |
|
190 |
|
191 VMFunction() |
|
192 : wrapped(nullptr), |
|
193 explicitArgs(0), |
|
194 argumentProperties(0), |
|
195 argumentPassedInFloatRegs(0), |
|
196 outParam(Type_Void), |
|
197 returnType(Type_Void), |
|
198 outParamRootType(RootNone), |
|
199 executionMode(SequentialExecution), |
|
200 extraValuesToPop(0) |
|
201 { |
|
202 } |
|
203 |
|
204 |
|
205 VMFunction(void *wrapped, uint32_t explicitArgs, uint32_t argumentProperties, |
|
206 uint32_t argumentPassedInFloatRegs, uint64_t argRootTypes, |
|
207 DataType outParam, RootType outParamRootType, DataType returnType, |
|
208 ExecutionMode executionMode, uint32_t extraValuesToPop = 0) |
|
209 : wrapped(wrapped), |
|
210 explicitArgs(explicitArgs), |
|
211 argumentProperties(argumentProperties), |
|
212 argumentPassedInFloatRegs(argumentPassedInFloatRegs), |
|
213 outParam(outParam), |
|
214 returnType(returnType), |
|
215 argumentRootTypes(argRootTypes), |
|
216 outParamRootType(outParamRootType), |
|
217 executionMode(executionMode), |
|
218 extraValuesToPop(extraValuesToPop) |
|
219 { |
|
220 // Check for valid failure/return type. |
|
221 JS_ASSERT_IF(outParam != Type_Void && executionMode == SequentialExecution, |
|
222 returnType == Type_Bool); |
|
223 JS_ASSERT(returnType == Type_Bool || |
|
224 returnType == Type_Object); |
|
225 } |
|
226 |
|
227 VMFunction(const VMFunction &o) { |
|
228 init(o); |
|
229 } |
|
230 |
|
231 void init(const VMFunction &o) { |
|
232 JS_ASSERT(!wrapped); |
|
233 *this = o; |
|
234 addToFunctions(); |
|
235 } |
|
236 |
|
237 private: |
|
238 // Add this to the global list of VMFunctions. |
|
239 void addToFunctions(); |
|
240 }; |
|
241 |
|
242 // A collection of VM functions for each execution mode. |
|
243 struct VMFunctionsModal |
|
244 { |
|
245 VMFunctionsModal(const VMFunction &info) { |
|
246 add(info); |
|
247 } |
|
248 VMFunctionsModal(const VMFunction &info1, const VMFunction &info2) { |
|
249 add(info1); |
|
250 add(info2); |
|
251 } |
|
252 |
|
253 inline const VMFunction &operator[](ExecutionMode mode) const { |
|
254 JS_ASSERT((unsigned)mode < NumExecutionModes); |
|
255 return funs_[mode]; |
|
256 } |
|
257 |
|
258 private: |
|
259 void add(const VMFunction &info) { |
|
260 JS_ASSERT((unsigned)info.executionMode < NumExecutionModes); |
|
261 funs_[info.executionMode].init(info); |
|
262 } |
|
263 |
|
264 mozilla::Array<VMFunction, NumExecutionModes> funs_; |
|
265 }; |
|
266 |
|
267 template <class> struct TypeToDataType { /* Unexpected return type for a VMFunction. */ }; |
|
268 template <> struct TypeToDataType<bool> { static const DataType result = Type_Bool; }; |
|
269 template <> struct TypeToDataType<JSObject *> { static const DataType result = Type_Object; }; |
|
270 template <> struct TypeToDataType<DeclEnvObject *> { static const DataType result = Type_Object; }; |
|
271 template <> struct TypeToDataType<JSString *> { static const DataType result = Type_Object; }; |
|
272 template <> struct TypeToDataType<JSFlatString *> { static const DataType result = Type_Object; }; |
|
273 template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; }; |
|
274 template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; }; |
|
275 template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; }; |
|
276 template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; }; |
|
277 template <> struct TypeToDataType<Handle<StaticWithObject *> > { static const DataType result = Type_Handle; }; |
|
278 template <> struct TypeToDataType<Handle<StaticBlockObject *> > { static const DataType result = Type_Handle; }; |
|
279 template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; }; |
|
280 template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; }; |
|
281 template <> struct TypeToDataType<MutableHandleValue> { static const DataType result = Type_Handle; }; |
|
282 |
|
283 // Convert argument types to properties of the argument known by the jit. |
|
284 template <class T> struct TypeToArgProperties { |
|
285 static const uint32_t result = |
|
286 (sizeof(T) <= sizeof(void *) ? VMFunction::Word : VMFunction::Double); |
|
287 }; |
|
288 template <> struct TypeToArgProperties<const Value &> { |
|
289 static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; |
|
290 }; |
|
291 template <> struct TypeToArgProperties<HandleObject> { |
|
292 static const uint32_t result = TypeToArgProperties<JSObject *>::result | VMFunction::ByRef; |
|
293 }; |
|
294 template <> struct TypeToArgProperties<HandleString> { |
|
295 static const uint32_t result = TypeToArgProperties<JSString *>::result | VMFunction::ByRef; |
|
296 }; |
|
297 template <> struct TypeToArgProperties<HandlePropertyName> { |
|
298 static const uint32_t result = TypeToArgProperties<PropertyName *>::result | VMFunction::ByRef; |
|
299 }; |
|
300 template <> struct TypeToArgProperties<HandleFunction> { |
|
301 static const uint32_t result = TypeToArgProperties<JSFunction *>::result | VMFunction::ByRef; |
|
302 }; |
|
303 template <> struct TypeToArgProperties<Handle<StaticWithObject *> > { |
|
304 static const uint32_t result = TypeToArgProperties<StaticWithObject *>::result | VMFunction::ByRef; |
|
305 }; |
|
306 template <> struct TypeToArgProperties<Handle<StaticBlockObject *> > { |
|
307 static const uint32_t result = TypeToArgProperties<StaticBlockObject *>::result | VMFunction::ByRef; |
|
308 }; |
|
309 template <> struct TypeToArgProperties<HandleScript> { |
|
310 static const uint32_t result = TypeToArgProperties<JSScript *>::result | VMFunction::ByRef; |
|
311 }; |
|
312 template <> struct TypeToArgProperties<HandleValue> { |
|
313 static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; |
|
314 }; |
|
315 template <> struct TypeToArgProperties<MutableHandleValue> { |
|
316 static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; |
|
317 }; |
|
318 template <> struct TypeToArgProperties<HandleShape> { |
|
319 static const uint32_t result = TypeToArgProperties<Shape *>::result | VMFunction::ByRef; |
|
320 }; |
|
321 template <> struct TypeToArgProperties<HandleTypeObject> { |
|
322 static const uint32_t result = TypeToArgProperties<types::TypeObject *>::result | VMFunction::ByRef; |
|
323 }; |
|
324 |
|
325 // Convert argument type to whether or not it should be passed in a float |
|
326 // register on platforms that have them, like x64. |
|
327 template <class T> struct TypeToPassInFloatReg { |
|
328 static const uint32_t result = 0; |
|
329 }; |
|
330 template <> struct TypeToPassInFloatReg<double> { |
|
331 static const uint32_t result = 1; |
|
332 }; |
|
333 |
|
334 // Convert argument types to root types used by the gc, see MarkJitExitFrame. |
|
335 template <class T> struct TypeToRootType { |
|
336 static const uint32_t result = VMFunction::RootNone; |
|
337 }; |
|
338 template <> struct TypeToRootType<HandleObject> { |
|
339 static const uint32_t result = VMFunction::RootObject; |
|
340 }; |
|
341 template <> struct TypeToRootType<HandleString> { |
|
342 static const uint32_t result = VMFunction::RootString; |
|
343 }; |
|
344 template <> struct TypeToRootType<HandlePropertyName> { |
|
345 static const uint32_t result = VMFunction::RootPropertyName; |
|
346 }; |
|
347 template <> struct TypeToRootType<HandleFunction> { |
|
348 static const uint32_t result = VMFunction::RootFunction; |
|
349 }; |
|
350 template <> struct TypeToRootType<HandleValue> { |
|
351 static const uint32_t result = VMFunction::RootValue; |
|
352 }; |
|
353 template <> struct TypeToRootType<MutableHandleValue> { |
|
354 static const uint32_t result = VMFunction::RootValue; |
|
355 }; |
|
356 template <> struct TypeToRootType<HandleShape> { |
|
357 static const uint32_t result = VMFunction::RootCell; |
|
358 }; |
|
359 template <> struct TypeToRootType<HandleTypeObject> { |
|
360 static const uint32_t result = VMFunction::RootCell; |
|
361 }; |
|
362 template <> struct TypeToRootType<HandleScript> { |
|
363 static const uint32_t result = VMFunction::RootCell; |
|
364 }; |
|
365 template <> struct TypeToRootType<Handle<StaticBlockObject *> > { |
|
366 static const uint32_t result = VMFunction::RootObject; |
|
367 }; |
|
368 template <> struct TypeToRootType<Handle<StaticWithObject *> > { |
|
369 static const uint32_t result = VMFunction::RootCell; |
|
370 }; |
|
371 template <class T> struct TypeToRootType<Handle<T> > { |
|
372 // Fail for Handle types that aren't specialized above. |
|
373 }; |
|
374 |
|
375 template <class> struct OutParamToDataType { static const DataType result = Type_Void; }; |
|
376 template <> struct OutParamToDataType<Value *> { static const DataType result = Type_Value; }; |
|
377 template <> struct OutParamToDataType<int *> { static const DataType result = Type_Int32; }; |
|
378 template <> struct OutParamToDataType<uint32_t *> { static const DataType result = Type_Int32; }; |
|
379 template <> struct OutParamToDataType<uint8_t **> { static const DataType result = Type_Pointer; }; |
|
380 template <> struct OutParamToDataType<bool *> { static const DataType result = Type_Bool; }; |
|
381 template <> struct OutParamToDataType<double *> { static const DataType result = Type_Double; }; |
|
382 template <> struct OutParamToDataType<MutableHandleValue> { static const DataType result = Type_Handle; }; |
|
383 template <> struct OutParamToDataType<MutableHandleObject> { static const DataType result = Type_Handle; }; |
|
384 template <> struct OutParamToDataType<MutableHandleString> { static const DataType result = Type_Handle; }; |
|
385 |
|
386 template <class> struct OutParamToRootType { |
|
387 static const VMFunction::RootType result = VMFunction::RootNone; |
|
388 }; |
|
389 template <> struct OutParamToRootType<MutableHandleValue> { |
|
390 static const VMFunction::RootType result = VMFunction::RootValue; |
|
391 }; |
|
392 template <> struct OutParamToRootType<MutableHandleObject> { |
|
393 static const VMFunction::RootType result = VMFunction::RootObject; |
|
394 }; |
|
395 template <> struct OutParamToRootType<MutableHandleString> { |
|
396 static const VMFunction::RootType result = VMFunction::RootString; |
|
397 }; |
|
398 |
|
399 template <class> struct MatchContext { }; |
|
400 template <> struct MatchContext<JSContext *> { |
|
401 static const ExecutionMode execMode = SequentialExecution; |
|
402 }; |
|
403 template <> struct MatchContext<ExclusiveContext *> { |
|
404 static const ExecutionMode execMode = SequentialExecution; |
|
405 }; |
|
406 template <> struct MatchContext<ForkJoinContext *> { |
|
407 static const ExecutionMode execMode = ParallelExecution; |
|
408 }; |
|
409 template <> struct MatchContext<ThreadSafeContext *> { |
|
410 // ThreadSafeContext functions can be called from either mode, but for |
|
411 // calling from parallel they should be wrapped first, so we default to |
|
412 // SequentialExecution here. |
|
413 static const ExecutionMode execMode = SequentialExecution; |
|
414 }; |
|
415 |
|
416 #define FOR_EACH_ARGS_1(Macro, Sep, Last) Macro(1) Last(1) |
|
417 #define FOR_EACH_ARGS_2(Macro, Sep, Last) FOR_EACH_ARGS_1(Macro, Sep, Sep) Macro(2) Last(2) |
|
418 #define FOR_EACH_ARGS_3(Macro, Sep, Last) FOR_EACH_ARGS_2(Macro, Sep, Sep) Macro(3) Last(3) |
|
419 #define FOR_EACH_ARGS_4(Macro, Sep, Last) FOR_EACH_ARGS_3(Macro, Sep, Sep) Macro(4) Last(4) |
|
420 #define FOR_EACH_ARGS_5(Macro, Sep, Last) FOR_EACH_ARGS_4(Macro, Sep, Sep) Macro(5) Last(5) |
|
421 #define FOR_EACH_ARGS_6(Macro, Sep, Last) FOR_EACH_ARGS_5(Macro, Sep, Sep) Macro(6) Last(6) |
|
422 |
|
423 #define COMPUTE_INDEX(NbArg) NbArg |
|
424 #define COMPUTE_OUTPARAM_RESULT(NbArg) OutParamToDataType<A ## NbArg>::result |
|
425 #define COMPUTE_OUTPARAM_ROOT(NbArg) OutParamToRootType<A ## NbArg>::result |
|
426 #define COMPUTE_ARG_PROP(NbArg) (TypeToArgProperties<A ## NbArg>::result << (2 * (NbArg - 1))) |
|
427 #define COMPUTE_ARG_ROOT(NbArg) (uint64_t(TypeToRootType<A ## NbArg>::result) << (3 * (NbArg - 1))) |
|
428 #define COMPUTE_ARG_FLOAT(NbArg) (TypeToPassInFloatReg<A ## NbArg>::result) << (NbArg - 1) |
|
429 #define SEP_OR(_) | |
|
430 #define NOTHING(_) |
|
431 |
|
432 #define FUNCTION_INFO_STRUCT_BODY(ForEachNb) \ |
|
433 static inline ExecutionMode executionMode() { \ |
|
434 return MatchContext<Context>::execMode; \ |
|
435 } \ |
|
436 static inline DataType returnType() { \ |
|
437 return TypeToDataType<R>::result; \ |
|
438 } \ |
|
439 static inline DataType outParam() { \ |
|
440 return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_RESULT); \ |
|
441 } \ |
|
442 static inline RootType outParamRootType() { \ |
|
443 return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_ROOT); \ |
|
444 } \ |
|
445 static inline size_t NbArgs() { \ |
|
446 return ForEachNb(NOTHING, NOTHING, COMPUTE_INDEX); \ |
|
447 } \ |
|
448 static inline size_t explicitArgs() { \ |
|
449 return NbArgs() - (outParam() != Type_Void ? 1 : 0); \ |
|
450 } \ |
|
451 static inline uint32_t argumentProperties() { \ |
|
452 return ForEachNb(COMPUTE_ARG_PROP, SEP_OR, NOTHING); \ |
|
453 } \ |
|
454 static inline uint32_t argumentPassedInFloatRegs() { \ |
|
455 return ForEachNb(COMPUTE_ARG_FLOAT, SEP_OR, NOTHING); \ |
|
456 } \ |
|
457 static inline uint64_t argumentRootTypes() { \ |
|
458 return ForEachNb(COMPUTE_ARG_ROOT, SEP_OR, NOTHING); \ |
|
459 } \ |
|
460 FunctionInfo(pf fun, PopValues extraValuesToPop = PopValues(0)) \ |
|
461 : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(), \ |
|
462 argumentProperties(), argumentPassedInFloatRegs(), \ |
|
463 argumentRootTypes(), outParam(), outParamRootType(), \ |
|
464 returnType(), executionMode(), \ |
|
465 extraValuesToPop.numValues) \ |
|
466 { } |
|
467 |
|
468 template <typename Fun> |
|
469 struct FunctionInfo { |
|
470 }; |
|
471 |
|
472 // VMFunction wrapper with no explicit arguments. |
|
473 template <class R, class Context> |
|
474 struct FunctionInfo<R (*)(Context)> : public VMFunction { |
|
475 typedef R (*pf)(Context); |
|
476 |
|
477 static inline ExecutionMode executionMode() { |
|
478 return MatchContext<Context>::execMode; |
|
479 } |
|
480 static inline DataType returnType() { |
|
481 return TypeToDataType<R>::result; |
|
482 } |
|
483 static inline DataType outParam() { |
|
484 return Type_Void; |
|
485 } |
|
486 static inline RootType outParamRootType() { |
|
487 return RootNone; |
|
488 } |
|
489 static inline size_t explicitArgs() { |
|
490 return 0; |
|
491 } |
|
492 static inline uint32_t argumentProperties() { |
|
493 return 0; |
|
494 } |
|
495 static inline uint32_t argumentPassedInFloatRegs() { |
|
496 return 0; |
|
497 } |
|
498 static inline uint64_t argumentRootTypes() { |
|
499 return 0; |
|
500 } |
|
501 FunctionInfo(pf fun) |
|
502 : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(), |
|
503 argumentProperties(), argumentPassedInFloatRegs(), |
|
504 argumentRootTypes(), outParam(), outParamRootType(), |
|
505 returnType(), executionMode()) |
|
506 { } |
|
507 }; |
|
508 |
|
509 // Specialize the class for each number of argument used by VMFunction. |
|
510 // Keep it verbose unless you find a readable macro for it. |
|
511 template <class R, class Context, class A1> |
|
512 struct FunctionInfo<R (*)(Context, A1)> : public VMFunction { |
|
513 typedef R (*pf)(Context, A1); |
|
514 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1) |
|
515 }; |
|
516 |
|
517 template <class R, class Context, class A1, class A2> |
|
518 struct FunctionInfo<R (*)(Context, A1, A2)> : public VMFunction { |
|
519 typedef R (*pf)(Context, A1, A2); |
|
520 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2) |
|
521 }; |
|
522 |
|
523 template <class R, class Context, class A1, class A2, class A3> |
|
524 struct FunctionInfo<R (*)(Context, A1, A2, A3)> : public VMFunction { |
|
525 typedef R (*pf)(Context, A1, A2, A3); |
|
526 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3) |
|
527 }; |
|
528 |
|
529 template <class R, class Context, class A1, class A2, class A3, class A4> |
|
530 struct FunctionInfo<R (*)(Context, A1, A2, A3, A4)> : public VMFunction { |
|
531 typedef R (*pf)(Context, A1, A2, A3, A4); |
|
532 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4) |
|
533 }; |
|
534 |
|
535 template <class R, class Context, class A1, class A2, class A3, class A4, class A5> |
|
536 struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5)> : public VMFunction { |
|
537 typedef R (*pf)(Context, A1, A2, A3, A4, A5); |
|
538 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5) |
|
539 }; |
|
540 |
|
541 template <class R, class Context, class A1, class A2, class A3, class A4, class A5, class A6> |
|
542 struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5, A6)> : public VMFunction { |
|
543 typedef R (*pf)(Context, A1, A2, A3, A4, A5, A6); |
|
544 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_6) |
|
545 }; |
|
546 |
|
547 #undef FUNCTION_INFO_STRUCT_BODY |
|
548 |
|
549 #undef FOR_EACH_ARGS_6 |
|
550 #undef FOR_EACH_ARGS_5 |
|
551 #undef FOR_EACH_ARGS_4 |
|
552 #undef FOR_EACH_ARGS_3 |
|
553 #undef FOR_EACH_ARGS_2 |
|
554 #undef FOR_EACH_ARGS_1 |
|
555 |
|
556 #undef COMPUTE_INDEX |
|
557 #undef COMPUTE_OUTPARAM_RESULT |
|
558 #undef COMPUTE_OUTPARAM_ROOT |
|
559 #undef COMPUTE_ARG_PROP |
|
560 #undef COMPUTE_ARG_FLOAT |
|
561 #undef SEP_OR |
|
562 #undef NOTHING |
|
563 |
|
564 class AutoDetectInvalidation |
|
565 { |
|
566 JSContext *cx_; |
|
567 IonScript *ionScript_; |
|
568 Value *rval_; |
|
569 bool disabled_; |
|
570 |
|
571 public: |
|
572 AutoDetectInvalidation(JSContext *cx, Value *rval, IonScript *ionScript = nullptr); |
|
573 |
|
574 void disable() { |
|
575 JS_ASSERT(!disabled_); |
|
576 disabled_ = true; |
|
577 } |
|
578 |
|
579 ~AutoDetectInvalidation() { |
|
580 if (!disabled_ && ionScript_->invalidated()) |
|
581 cx_->runtime()->setIonReturnOverride(*rval_); |
|
582 } |
|
583 }; |
|
584 |
|
585 bool InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Value *rval); |
|
586 JSObject *NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap); |
|
587 |
|
588 bool CheckOverRecursed(JSContext *cx); |
|
589 bool CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame, |
|
590 uint32_t extra, uint32_t earlyCheck); |
|
591 |
|
592 bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); |
|
593 bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval); |
|
594 bool MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value); |
|
595 bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value); |
|
596 |
|
597 template<bool Equal> |
|
598 bool LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); |
|
599 |
|
600 template<bool Equal> |
|
601 bool StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); |
|
602 |
|
603 bool LessThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); |
|
604 bool LessThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); |
|
605 bool GreaterThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); |
|
606 bool GreaterThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); |
|
607 |
|
608 template<bool Equal> |
|
609 bool StringsEqual(JSContext *cx, HandleString left, HandleString right, bool *res); |
|
610 |
|
611 bool IteratorMore(JSContext *cx, HandleObject obj, bool *res); |
|
612 |
|
613 // Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT and parallel array inlining |
|
614 JSObject *NewInitParallelArray(JSContext *cx, HandleObject templateObj); |
|
615 JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type); |
|
616 JSObject *NewInitObject(JSContext *cx, HandleObject templateObject); |
|
617 JSObject *NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject); |
|
618 |
|
619 bool ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval); |
|
620 bool ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length); |
|
621 bool ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval); |
|
622 JSObject *ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject res); |
|
623 |
|
624 bool CharCodeAt(JSContext *cx, HandleString str, int32_t index, uint32_t *code); |
|
625 JSFlatString *StringFromCharCode(JSContext *cx, int32_t code); |
|
626 |
|
627 bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, |
|
628 bool strict, jsbytecode *pc); |
|
629 |
|
630 bool InterruptCheck(JSContext *cx); |
|
631 |
|
632 HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots); |
|
633 JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots); |
|
634 JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots); |
|
635 JSObject *NewStringObject(JSContext *cx, HandleString str); |
|
636 |
|
637 bool SPSEnter(JSContext *cx, HandleScript script); |
|
638 bool SPSExit(JSContext *cx, HandleScript script); |
|
639 |
|
640 bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, bool *out); |
|
641 bool OperatorInI(JSContext *cx, uint32_t index, HandleObject obj, bool *out); |
|
642 |
|
643 bool GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rval); |
|
644 |
|
645 bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval); |
|
646 |
|
647 void GetDynamicName(JSContext *cx, JSObject *scopeChain, JSString *str, Value *vp); |
|
648 |
|
649 bool FilterArgumentsOrEval(JSContext *cx, JSString *str); |
|
650 |
|
651 #ifdef JSGC_GENERATIONAL |
|
652 void PostWriteBarrier(JSRuntime *rt, JSObject *obj); |
|
653 void PostGlobalWriteBarrier(JSRuntime *rt, JSObject *obj); |
|
654 #endif |
|
655 |
|
656 uint32_t GetIndexFromString(JSString *str); |
|
657 |
|
658 bool DebugPrologue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn); |
|
659 bool DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok); |
|
660 |
|
661 bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame); |
|
662 bool HeavyweightFunPrologue(JSContext *cx, BaselineFrame *frame); |
|
663 |
|
664 bool NewArgumentsObject(JSContext *cx, BaselineFrame *frame, MutableHandleValue res); |
|
665 |
|
666 JSObject *InitRestParameter(JSContext *cx, uint32_t length, Value *rest, HandleObject templateObj, |
|
667 HandleObject res); |
|
668 |
|
669 bool HandleDebugTrap(JSContext *cx, BaselineFrame *frame, uint8_t *retAddr, bool *mustReturn); |
|
670 bool OnDebuggerStatement(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn); |
|
671 |
|
672 bool EnterWith(JSContext *cx, BaselineFrame *frame, HandleValue val, |
|
673 Handle<StaticWithObject *> templ); |
|
674 bool LeaveWith(JSContext *cx, BaselineFrame *frame); |
|
675 |
|
676 bool PushBlockScope(JSContext *cx, BaselineFrame *frame, Handle<StaticBlockObject *> block); |
|
677 bool PopBlockScope(JSContext *cx, BaselineFrame *frame); |
|
678 bool DebugLeaveBlock(JSContext *cx, BaselineFrame *frame, jsbytecode *pc); |
|
679 |
|
680 bool InitBaselineFrameForOsr(BaselineFrame *frame, InterpreterFrame *interpFrame, |
|
681 uint32_t numStackValues); |
|
682 |
|
683 JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject descr, |
|
684 HandleObject owner, int32_t offset); |
|
685 |
|
686 bool ArraySpliceDense(JSContext *cx, HandleObject obj, uint32_t start, uint32_t deleteCount); |
|
687 |
|
688 bool Recompile(JSContext *cx); |
|
689 JSString *RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp, |
|
690 HandleString repl); |
|
691 JSString *StringReplace(JSContext *cx, HandleString string, HandleString pattern, |
|
692 HandleString repl); |
|
693 |
|
694 bool SetDenseElement(JSContext *cx, HandleObject obj, int32_t index, HandleValue value, |
|
695 bool strict); |
|
696 |
|
697 #ifdef DEBUG |
|
698 void AssertValidObjectPtr(JSContext *cx, JSObject *obj); |
|
699 void AssertValidStringPtr(JSContext *cx, JSString *str); |
|
700 void AssertValidValue(JSContext *cx, Value *v); |
|
701 #endif |
|
702 |
|
703 } // namespace jit |
|
704 } // namespace js |
|
705 |
|
706 #endif /* jit_VMFunctions_h */ |