Line data Source code
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 "mozilla/Attributes.h"
11 :
12 : #include "jspubtd.h"
13 :
14 : #include "jit/CompileInfo.h"
15 : #include "jit/JitFrames.h"
16 : #include "vm/Interpreter.h"
17 :
18 : namespace js {
19 :
20 : class NamedLambdaObject;
21 : class WithScope;
22 : class InlineTypedObject;
23 : class GeneratorObject;
24 : class RegExpObject;
25 : class TypedArrayObject;
26 :
27 : namespace jit {
28 :
29 : enum DataType {
30 : Type_Void,
31 : Type_Bool,
32 : Type_Int32,
33 : Type_Double,
34 : Type_Pointer,
35 : Type_Object,
36 : Type_Value,
37 : Type_Handle
38 : };
39 :
40 : struct PopValues
41 : {
42 : uint32_t numValues;
43 :
44 777 : explicit PopValues(uint32_t numValues)
45 777 : : numValues(numValues)
46 777 : { }
47 : };
48 :
49 : enum MaybeTailCall {
50 : TailCall,
51 : NonTailCall
52 : };
53 :
54 : // Contains information about a virtual machine function that can be called
55 : // from JIT code. Functions described in this manner must conform to a simple
56 : // protocol: the return type must have a special "failure" value (for example,
57 : // false for bool, or nullptr for Objects). If the function is designed to
58 : // return a value that does not meet this requirement - such as
59 : // object-or-nullptr, or an integer, an optional, final outParam can be
60 : // specified. In this case, the return type must be boolean to indicate
61 : // failure.
62 : //
63 : // All functions described by VMFunction take a JSContext * as a first
64 : // argument, and are treated as re-entrant into the VM and therefore fallible.
65 : struct VMFunction
66 : {
67 : // Global linked list of all VMFunctions.
68 : static VMFunction* functions;
69 : VMFunction* next;
70 :
71 : // Address of the C function.
72 : void* wrapped;
73 :
74 : const char* name_;
75 :
76 : // Number of arguments expected, excluding JSContext * as an implicit
77 : // first argument and an outparam as a possible implicit final argument.
78 : uint32_t explicitArgs;
79 :
80 : enum ArgProperties {
81 : WordByValue = 0,
82 : DoubleByValue = 1,
83 : WordByRef = 2,
84 : DoubleByRef = 3,
85 : // BitMask version.
86 : Word = 0,
87 : Double = 1,
88 : ByRef = 2
89 : };
90 :
91 : // Contains properties about the first 16 arguments.
92 : uint32_t argumentProperties;
93 :
94 : // Which arguments should be passed in float register on platforms that
95 : // have them.
96 : uint32_t argumentPassedInFloatRegs;
97 :
98 : // The outparam may be any Type_*, and must be the final argument to the
99 : // function, if not Void. outParam != Void implies that the return type
100 : // has a boolean failure mode.
101 : DataType outParam;
102 :
103 : // Type returned by the C function and used by the VMFunction wrapper to
104 : // check for failures of the C function. Valid failure/return types are
105 : // boolean and object pointers which are asserted inside the VMFunction
106 : // constructor. If the C function use an outparam (!= Type_Void), then
107 : // the only valid failure/return type is boolean -- object pointers are
108 : // pointless because the wrapper will only use it to compare it against
109 : // nullptr before discarding its value.
110 : DataType returnType;
111 :
112 : // Note: a maximum of seven root types is supported.
113 : enum RootType {
114 : RootNone = 0,
115 : RootObject,
116 : RootString,
117 : RootId,
118 : RootFunction,
119 : RootValue,
120 : RootCell
121 : };
122 :
123 : // Contains an combination of enumerated types used by the gc for marking
124 : // arguments of the VM wrapper.
125 : uint64_t argumentRootTypes;
126 :
127 : // The root type of the out param if outParam == Type_Handle.
128 : RootType outParamRootType;
129 :
130 : // Number of Values the VM wrapper should pop from the stack when it returns.
131 : // Used by baseline IC stubs so that they can use tail calls to call the VM
132 : // wrapper.
133 : uint32_t extraValuesToPop;
134 :
135 : // On some architectures, called functions need to explicitly push their
136 : // return address, for a tail call, there is nothing to push, so tail-callness
137 : // needs to be known at compile time.
138 : MaybeTailCall expectTailCall;
139 :
140 : uint32_t argc() const {
141 : // JSContext * + args + (OutParam? *)
142 : return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1);
143 : }
144 :
145 1036 : DataType failType() const {
146 1036 : return returnType;
147 : }
148 :
149 2387 : ArgProperties argProperties(uint32_t explicitArg) const {
150 2387 : return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3);
151 : }
152 :
153 71 : RootType argRootType(uint32_t explicitArg) const {
154 71 : return RootType((argumentRootTypes >> (3 * explicitArg)) & 7);
155 : }
156 :
157 844 : bool argPassedInFloatReg(uint32_t explicitArg) const {
158 844 : return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1;
159 : }
160 :
161 0 : const char* name() const {
162 0 : return name_;
163 : }
164 :
165 : // Return the stack size consumed by explicit arguments.
166 5440 : size_t explicitStackSlots() const {
167 5440 : size_t stackSlots = explicitArgs;
168 :
169 : // Fetch all double-word flags of explicit arguments.
170 : uint32_t n =
171 5440 : ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
172 5440 : & 0x55555555 // = Mask double-size args.
173 5440 : & argumentProperties;
174 :
175 : // Add the number of double-word flags. (expect a few loop
176 : // iteration)
177 5440 : while (n) {
178 0 : stackSlots++;
179 0 : n &= n - 1;
180 : }
181 5440 : return stackSlots;
182 : }
183 :
184 : // Double-size argument which are passed by value are taking the space
185 : // of 2 C arguments. This function is used to compute the number of
186 : // argument expected by the C function. This is not the same as
187 : // explicitStackSlots because reference to stack slots may take one less
188 : // register in the total count.
189 : size_t explicitArgc() const {
190 : size_t stackSlots = explicitArgs;
191 :
192 : // Fetch all explicit arguments.
193 : uint32_t n =
194 : ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
195 : & argumentProperties;
196 :
197 : // Filter double-size arguments (0x5 = 0b0101) and remove (& ~)
198 : // arguments passed by reference (0b1010 >> 1 == 0b0101).
199 : n = (n & 0x55555555) & ~(n >> 1);
200 :
201 : // Add the number of double-word transfered by value. (expect a few
202 : // loop iteration)
203 : while (n) {
204 : stackSlots++;
205 : n &= n - 1;
206 : }
207 : return stackSlots;
208 : }
209 :
210 : size_t doubleByRefArgs() const {
211 : size_t count = 0;
212 :
213 : // Fetch all explicit arguments.
214 : uint32_t n =
215 : ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
216 : & argumentProperties;
217 :
218 : // Filter double-size arguments (0x5 = 0b0101) and take (&) only
219 : // arguments passed by reference (0b1010 >> 1 == 0b0101).
220 : n = (n & 0x55555555) & (n >> 1);
221 :
222 : // Add the number of double-word transfered by refference. (expect a
223 : // few loop iterations)
224 : while (n) {
225 : count++;
226 : n &= n - 1;
227 : }
228 : return count;
229 : }
230 :
231 : constexpr
232 777 : VMFunction(void* wrapped, const char* name, uint32_t explicitArgs, uint32_t argumentProperties,
233 : uint32_t argumentPassedInFloatRegs, uint64_t argRootTypes,
234 : DataType outParam, RootType outParamRootType, DataType returnType,
235 : uint32_t extraValuesToPop = 0, MaybeTailCall expectTailCall = NonTailCall)
236 777 : : next(nullptr),
237 : wrapped(wrapped),
238 : name_(name),
239 : explicitArgs(explicitArgs),
240 : argumentProperties(argumentProperties),
241 : argumentPassedInFloatRegs(argumentPassedInFloatRegs),
242 : outParam(outParam),
243 : returnType(returnType),
244 : argumentRootTypes(argRootTypes),
245 : outParamRootType(outParamRootType),
246 : extraValuesToPop(extraValuesToPop),
247 777 : expectTailCall(expectTailCall)
248 777 : { }
249 :
250 777 : VMFunction(const VMFunction& o)
251 777 : : next(nullptr),
252 777 : wrapped(o.wrapped),
253 777 : name_(o.name_),
254 777 : explicitArgs(o.explicitArgs),
255 777 : argumentProperties(o.argumentProperties),
256 777 : argumentPassedInFloatRegs(o.argumentPassedInFloatRegs),
257 777 : outParam(o.outParam),
258 777 : returnType(o.returnType),
259 777 : argumentRootTypes(o.argumentRootTypes),
260 777 : outParamRootType(o.outParamRootType),
261 777 : extraValuesToPop(o.extraValuesToPop),
262 8547 : expectTailCall(o.expectTailCall)
263 : {
264 : // Check for valid failure/return type.
265 777 : MOZ_ASSERT_IF(outParam != Type_Void, returnType == Type_Bool);
266 777 : MOZ_ASSERT(returnType == Type_Bool ||
267 : returnType == Type_Object);
268 777 : addToFunctions();
269 777 : }
270 :
271 : private:
272 : // Add this to the global list of VMFunctions.
273 : void addToFunctions();
274 : };
275 :
276 : template <class> struct TypeToDataType { /* Unexpected return type for a VMFunction. */ };
277 : template <> struct TypeToDataType<bool> { static const DataType result = Type_Bool; };
278 : template <> struct TypeToDataType<JSObject*> { static const DataType result = Type_Object; };
279 : template <> struct TypeToDataType<JSFunction*> { static const DataType result = Type_Object; };
280 : template <> struct TypeToDataType<NativeObject*> { static const DataType result = Type_Object; };
281 : template <> struct TypeToDataType<PlainObject*> { static const DataType result = Type_Object; };
282 : template <> struct TypeToDataType<InlineTypedObject*> { static const DataType result = Type_Object; };
283 : template <> struct TypeToDataType<NamedLambdaObject*> { static const DataType result = Type_Object; };
284 : template <> struct TypeToDataType<LexicalEnvironmentObject*> { static const DataType result = Type_Object; };
285 : template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
286 : template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
287 : template <> struct TypeToDataType<ArrayIteratorObject*> { static const DataType result = Type_Object; };
288 : template <> struct TypeToDataType<StringIteratorObject*> { static const DataType result = Type_Object; };
289 : template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
290 : template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; };
291 : template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
292 : template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; };
293 : template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; };
294 : template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; };
295 : template <> struct TypeToDataType<Handle<NativeObject*> > { static const DataType result = Type_Handle; };
296 : template <> struct TypeToDataType<Handle<InlineTypedObject*> > { static const DataType result = Type_Handle; };
297 : template <> struct TypeToDataType<Handle<ArrayObject*> > { static const DataType result = Type_Handle; };
298 : template <> struct TypeToDataType<Handle<GeneratorObject*> > { static const DataType result = Type_Handle; };
299 : template <> struct TypeToDataType<Handle<PlainObject*> > { static const DataType result = Type_Handle; };
300 : template <> struct TypeToDataType<Handle<WithScope*> > { static const DataType result = Type_Handle; };
301 : template <> struct TypeToDataType<Handle<LexicalScope*> > { static const DataType result = Type_Handle; };
302 : template <> struct TypeToDataType<Handle<Scope*> > { static const DataType result = Type_Handle; };
303 : template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; };
304 : template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; };
305 : template <> struct TypeToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
306 : template <> struct TypeToDataType<HandleId> { static const DataType result = Type_Handle; };
307 :
308 : // Convert argument types to properties of the argument known by the jit.
309 : template <class T> struct TypeToArgProperties {
310 : static const uint32_t result =
311 : (sizeof(T) <= sizeof(void*) ? VMFunction::Word : VMFunction::Double);
312 : };
313 : template <> struct TypeToArgProperties<const Value&> {
314 : static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
315 : };
316 : template <> struct TypeToArgProperties<HandleObject> {
317 : static const uint32_t result = TypeToArgProperties<JSObject*>::result | VMFunction::ByRef;
318 : };
319 : template <> struct TypeToArgProperties<HandleString> {
320 : static const uint32_t result = TypeToArgProperties<JSString*>::result | VMFunction::ByRef;
321 : };
322 : template <> struct TypeToArgProperties<HandlePropertyName> {
323 : static const uint32_t result = TypeToArgProperties<PropertyName*>::result | VMFunction::ByRef;
324 : };
325 : template <> struct TypeToArgProperties<HandleFunction> {
326 : static const uint32_t result = TypeToArgProperties<JSFunction*>::result | VMFunction::ByRef;
327 : };
328 : template <> struct TypeToArgProperties<Handle<NativeObject*> > {
329 : static const uint32_t result = TypeToArgProperties<NativeObject*>::result | VMFunction::ByRef;
330 : };
331 : template <> struct TypeToArgProperties<Handle<InlineTypedObject*> > {
332 : static const uint32_t result = TypeToArgProperties<InlineTypedObject*>::result | VMFunction::ByRef;
333 : };
334 : template <> struct TypeToArgProperties<Handle<ArrayObject*> > {
335 : static const uint32_t result = TypeToArgProperties<ArrayObject*>::result | VMFunction::ByRef;
336 : };
337 : template <> struct TypeToArgProperties<Handle<GeneratorObject*> > {
338 : static const uint32_t result = TypeToArgProperties<GeneratorObject*>::result | VMFunction::ByRef;
339 : };
340 : template <> struct TypeToArgProperties<Handle<PlainObject*> > {
341 : static const uint32_t result = TypeToArgProperties<PlainObject*>::result | VMFunction::ByRef;
342 : };
343 : template <> struct TypeToArgProperties<Handle<RegExpObject*> > {
344 : static const uint32_t result = TypeToArgProperties<RegExpObject*>::result | VMFunction::ByRef;
345 : };
346 : template <> struct TypeToArgProperties<Handle<WithScope*> > {
347 : static const uint32_t result = TypeToArgProperties<WithScope*>::result | VMFunction::ByRef;
348 : };
349 : template <> struct TypeToArgProperties<Handle<LexicalScope*> > {
350 : static const uint32_t result = TypeToArgProperties<LexicalScope*>::result | VMFunction::ByRef;
351 : };
352 : template <> struct TypeToArgProperties<Handle<Scope*> > {
353 : static const uint32_t result = TypeToArgProperties<Scope*>::result | VMFunction::ByRef;
354 : };
355 : template <> struct TypeToArgProperties<HandleScript> {
356 : static const uint32_t result = TypeToArgProperties<JSScript*>::result | VMFunction::ByRef;
357 : };
358 : template <> struct TypeToArgProperties<HandleValue> {
359 : static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
360 : };
361 : template <> struct TypeToArgProperties<MutableHandleValue> {
362 : static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
363 : };
364 : template <> struct TypeToArgProperties<HandleId> {
365 : static const uint32_t result = TypeToArgProperties<jsid>::result | VMFunction::ByRef;
366 : };
367 : template <> struct TypeToArgProperties<HandleShape> {
368 : static const uint32_t result = TypeToArgProperties<Shape*>::result | VMFunction::ByRef;
369 : };
370 : template <> struct TypeToArgProperties<HandleObjectGroup> {
371 : static const uint32_t result = TypeToArgProperties<ObjectGroup*>::result | VMFunction::ByRef;
372 : };
373 :
374 : // Convert argument type to whether or not it should be passed in a float
375 : // register on platforms that have them, like x64.
376 : template <class T> struct TypeToPassInFloatReg {
377 : static const uint32_t result = 0;
378 : };
379 : template <> struct TypeToPassInFloatReg<double> {
380 : static const uint32_t result = 1;
381 : };
382 :
383 : // Convert argument types to root types used by the gc, see MarkJitExitFrame.
384 : template <class T> struct TypeToRootType {
385 : static const uint32_t result = VMFunction::RootNone;
386 : };
387 : template <> struct TypeToRootType<HandleObject> {
388 : static const uint32_t result = VMFunction::RootObject;
389 : };
390 : template <> struct TypeToRootType<HandleString> {
391 : static const uint32_t result = VMFunction::RootString;
392 : };
393 : template <> struct TypeToRootType<HandlePropertyName> {
394 : static const uint32_t result = VMFunction::RootString;
395 : };
396 : template <> struct TypeToRootType<HandleFunction> {
397 : static const uint32_t result = VMFunction::RootFunction;
398 : };
399 : template <> struct TypeToRootType<HandleValue> {
400 : static const uint32_t result = VMFunction::RootValue;
401 : };
402 : template <> struct TypeToRootType<MutableHandleValue> {
403 : static const uint32_t result = VMFunction::RootValue;
404 : };
405 : template <> struct TypeToRootType<HandleId> {
406 : static const uint32_t result = VMFunction::RootId;
407 : };
408 : template <> struct TypeToRootType<HandleShape> {
409 : static const uint32_t result = VMFunction::RootCell;
410 : };
411 : template <> struct TypeToRootType<HandleObjectGroup> {
412 : static const uint32_t result = VMFunction::RootCell;
413 : };
414 : template <> struct TypeToRootType<HandleScript> {
415 : static const uint32_t result = VMFunction::RootCell;
416 : };
417 : template <> struct TypeToRootType<Handle<NativeObject*> > {
418 : static const uint32_t result = VMFunction::RootObject;
419 : };
420 : template <> struct TypeToRootType<Handle<InlineTypedObject*> > {
421 : static const uint32_t result = VMFunction::RootObject;
422 : };
423 : template <> struct TypeToRootType<Handle<ArrayObject*> > {
424 : static const uint32_t result = VMFunction::RootObject;
425 : };
426 : template <> struct TypeToRootType<Handle<GeneratorObject*> > {
427 : static const uint32_t result = VMFunction::RootObject;
428 : };
429 : template <> struct TypeToRootType<Handle<PlainObject*> > {
430 : static const uint32_t result = VMFunction::RootObject;
431 : };
432 : template <> struct TypeToRootType<Handle<RegExpObject*> > {
433 : static const uint32_t result = VMFunction::RootObject;
434 : };
435 : template <> struct TypeToRootType<Handle<LexicalScope*> > {
436 : static const uint32_t result = VMFunction::RootCell;
437 : };
438 : template <> struct TypeToRootType<Handle<WithScope*> > {
439 : static const uint32_t result = VMFunction::RootCell;
440 : };
441 : template <> struct TypeToRootType<Handle<Scope*> > {
442 : static const uint32_t result = VMFunction::RootCell;
443 : };
444 : template <class T> struct TypeToRootType<Handle<T> > {
445 : // Fail for Handle types that aren't specialized above.
446 : };
447 :
448 : template <class> struct OutParamToDataType { static const DataType result = Type_Void; };
449 : template <> struct OutParamToDataType<Value*> { static const DataType result = Type_Value; };
450 : template <> struct OutParamToDataType<int*> { static const DataType result = Type_Int32; };
451 : template <> struct OutParamToDataType<uint32_t*> { static const DataType result = Type_Int32; };
452 : template <> struct OutParamToDataType<uint8_t**> { static const DataType result = Type_Pointer; };
453 : template <> struct OutParamToDataType<bool*> { static const DataType result = Type_Bool; };
454 : template <> struct OutParamToDataType<double*> { static const DataType result = Type_Double; };
455 : template <> struct OutParamToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
456 : template <> struct OutParamToDataType<MutableHandleObject> { static const DataType result = Type_Handle; };
457 : template <> struct OutParamToDataType<MutableHandleString> { static const DataType result = Type_Handle; };
458 :
459 : template <class> struct OutParamToRootType {
460 : static const VMFunction::RootType result = VMFunction::RootNone;
461 : };
462 : template <> struct OutParamToRootType<MutableHandleValue> {
463 : static const VMFunction::RootType result = VMFunction::RootValue;
464 : };
465 : template <> struct OutParamToRootType<MutableHandleObject> {
466 : static const VMFunction::RootType result = VMFunction::RootObject;
467 : };
468 : template <> struct OutParamToRootType<MutableHandleString> {
469 : static const VMFunction::RootType result = VMFunction::RootString;
470 : };
471 :
472 : template <class> struct MatchContext { };
473 : template <> struct MatchContext<JSContext*> {
474 : static const bool valid = true;
475 : };
476 :
477 : // Extract the last element of a list of types.
478 : template <typename... ArgTypes>
479 : struct LastArg;
480 :
481 : template <>
482 : struct LastArg<>
483 : {
484 : typedef void Type;
485 : static constexpr size_t nbArgs = 0;
486 : };
487 :
488 : template <typename HeadType>
489 : struct LastArg<HeadType>
490 : {
491 : typedef HeadType Type;
492 : static constexpr size_t nbArgs = 1;
493 : };
494 :
495 : template <typename HeadType, typename... TailTypes>
496 : struct LastArg<HeadType, TailTypes...>
497 : {
498 : typedef typename LastArg<TailTypes...>::Type Type;
499 : static constexpr size_t nbArgs = LastArg<TailTypes...>::nbArgs + 1;
500 : };
501 :
502 : // Construct a bit mask from a list of types. The mask is constructed as an OR
503 : // of the mask produced for each argument. The result of each argument is
504 : // shifted by its index, such that the result of the first argument is on the
505 : // low bits of the mask, and the result of the last argument in part of the
506 : // high bits of the mask.
507 : template <template<typename> class Each, typename ResultType, size_t Shift,
508 : typename... Args>
509 : struct BitMask;
510 :
511 : template <template<typename> class Each, typename ResultType, size_t Shift>
512 : struct BitMask<Each, ResultType, Shift>
513 : {
514 : static constexpr ResultType result = ResultType();
515 : };
516 :
517 : template <template<typename> class Each, typename ResultType, size_t Shift,
518 : typename HeadType, typename... TailTypes>
519 : struct BitMask<Each, ResultType, Shift, HeadType, TailTypes...>
520 : {
521 : static_assert(ResultType(Each<HeadType>::result) < (1 << Shift),
522 : "not enough bits reserved by the shift for individual results");
523 : static_assert(LastArg<TailTypes...>::nbArgs < (8 * sizeof(ResultType) / Shift),
524 : "not enough bits in the result type to store all bit masks");
525 :
526 : static constexpr ResultType result =
527 : ResultType(Each<HeadType>::result) |
528 : (BitMask<Each, ResultType, Shift, TailTypes...>::result << Shift);
529 : };
530 :
531 : // Extract VMFunction properties based on the signature of the function. The
532 : // properties are used to generate the logic for calling the VM function, and
533 : // also for marking the stack during GCs.
534 : template <typename... Args>
535 : struct FunctionInfo;
536 :
537 : template <class R, class Context, typename... Args>
538 : struct FunctionInfo<R (*)(Context, Args...)> : public VMFunction
539 : {
540 : typedef R (*pf)(Context, Args...);
541 :
542 777 : static DataType returnType() {
543 777 : return TypeToDataType<R>::result;
544 : }
545 1554 : static DataType outParam() {
546 1554 : return OutParamToDataType<typename LastArg<Args...>::Type>::result;
547 : }
548 777 : static RootType outParamRootType() {
549 777 : return OutParamToRootType<typename LastArg<Args...>::Type>::result;
550 : }
551 777 : static size_t NbArgs() {
552 777 : return LastArg<Args...>::nbArgs;
553 : }
554 777 : static size_t explicitArgs() {
555 777 : return NbArgs() - (outParam() != Type_Void ? 1 : 0);
556 : }
557 777 : static uint32_t argumentProperties() {
558 777 : return BitMask<TypeToArgProperties, uint32_t, 2, Args...>::result;
559 : }
560 777 : static uint32_t argumentPassedInFloatRegs() {
561 777 : return BitMask<TypeToPassInFloatReg, uint32_t, 2, Args...>::result;
562 : }
563 777 : static uint64_t argumentRootTypes() {
564 777 : return BitMask<TypeToRootType, uint64_t, 3, Args...>::result;
565 : }
566 687 : explicit FunctionInfo(pf fun, const char* name, PopValues extraValuesToPop = PopValues(0))
567 687 : : VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), name, explicitArgs(),
568 : argumentProperties(), argumentPassedInFloatRegs(),
569 : argumentRootTypes(), outParam(), outParamRootType(),
570 1374 : returnType(), extraValuesToPop.numValues, NonTailCall)
571 : {
572 : static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction");
573 687 : }
574 90 : explicit FunctionInfo(pf fun, const char* name, MaybeTailCall expectTailCall,
575 : PopValues extraValuesToPop = PopValues(0))
576 90 : : VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), name, explicitArgs(),
577 : argumentProperties(), argumentPassedInFloatRegs(),
578 : argumentRootTypes(), outParam(), outParamRootType(),
579 180 : returnType(), extraValuesToPop.numValues, expectTailCall)
580 : {
581 : static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction");
582 90 : }
583 : };
584 :
585 : class AutoDetectInvalidation
586 : {
587 : JSContext* cx_;
588 : IonScript* ionScript_;
589 : MutableHandleValue rval_;
590 : bool disabled_;
591 :
592 : void setReturnOverride();
593 :
594 : public:
595 20 : AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval, IonScript* ionScript)
596 20 : : cx_(cx), ionScript_(ionScript), rval_(rval), disabled_(false)
597 : {
598 20 : MOZ_ASSERT(ionScript);
599 20 : }
600 :
601 : AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval);
602 :
603 0 : void disable() {
604 0 : MOZ_ASSERT(!disabled_);
605 0 : disabled_ = true;
606 0 : }
607 :
608 20 : bool shouldSetReturnOverride() const {
609 20 : return !disabled_ && ionScript_->invalidated();
610 : }
611 :
612 40 : ~AutoDetectInvalidation() {
613 20 : if (MOZ_UNLIKELY(shouldSetReturnOverride()))
614 0 : setReturnOverride();
615 20 : }
616 : };
617 :
618 : MOZ_MUST_USE bool
619 : InvokeFunction(JSContext* cx, HandleObject obj0, bool constructing, bool ignoresReturnValue,
620 : uint32_t argc, Value* argv, MutableHandleValue rval);
621 : MOZ_MUST_USE bool
622 : InvokeFunctionShuffleNewTarget(JSContext* cx, HandleObject obj, uint32_t numActualArgs,
623 : uint32_t numFormalArgs, Value* argv, MutableHandleValue rval);
624 :
625 : bool CheckOverRecursed(JSContext* cx);
626 : bool CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
627 : uint32_t extra, uint32_t earlyCheck);
628 :
629 : JSObject* BindVar(JSContext* cx, HandleObject scopeChain);
630 : MOZ_MUST_USE bool
631 : DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
632 : MOZ_MUST_USE bool
633 : DefLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
634 : MOZ_MUST_USE bool
635 : DefGlobalLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs);
636 : MOZ_MUST_USE bool
637 : MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value);
638 : MOZ_MUST_USE bool
639 : InitProp(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value,
640 : jsbytecode* pc);
641 :
642 : template<bool Equal>
643 : bool LooselyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
644 :
645 : template<bool Equal>
646 : bool StrictlyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
647 :
648 : bool LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
649 : bool LessThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
650 : bool GreaterThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
651 : bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
652 :
653 : template<bool Equal>
654 : bool StringsEqual(JSContext* cx, HandleString left, HandleString right, bool* res);
655 :
656 : MOZ_MUST_USE bool StringSplitHelper(JSContext* cx, HandleString str, HandleString sep,
657 : HandleObjectGroup group, uint32_t limit,
658 : MutableHandleValue result);
659 :
660 : MOZ_MUST_USE bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
661 : MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length);
662 : MOZ_MUST_USE bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
663 : JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep);
664 : MOZ_MUST_USE bool SetArrayLength(JSContext* cx, HandleObject obj, HandleValue value, bool strict);
665 :
666 : MOZ_MUST_USE bool
667 : CharCodeAt(JSContext* cx, HandleString str, int32_t index, uint32_t* code);
668 : JSFlatString* StringFromCharCode(JSContext* cx, int32_t code);
669 : JSString* StringFromCodePoint(JSContext* cx, int32_t codePoint);
670 :
671 : MOZ_MUST_USE bool
672 : SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value,
673 : bool strict, jsbytecode* pc);
674 :
675 : MOZ_MUST_USE bool
676 : InterruptCheck(JSContext* cx);
677 :
678 : void* MallocWrapper(JSRuntime* rt, size_t nbytes);
679 : JSObject* NewCallObject(JSContext* cx, HandleShape shape, HandleObjectGroup group);
680 : JSObject* NewSingletonCallObject(JSContext* cx, HandleShape shape);
681 : JSObject* NewStringObject(JSContext* cx, HandleString str);
682 :
683 : bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out);
684 : bool OperatorInI(JSContext* cx, uint32_t index, HandleObject obj, bool* out);
685 :
686 : MOZ_MUST_USE bool
687 : GetIntrinsicValue(JSContext* cx, HandlePropertyName name, MutableHandleValue rval);
688 :
689 : MOZ_MUST_USE bool
690 : CreateThis(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval);
691 :
692 : void GetDynamicName(JSContext* cx, JSObject* scopeChain, JSString* str, Value* vp);
693 :
694 : void PostWriteBarrier(JSRuntime* rt, JSObject* obj);
695 : void PostGlobalWriteBarrier(JSRuntime* rt, JSObject* obj);
696 :
697 : enum class IndexInBounds { Yes, Maybe };
698 :
699 : template <IndexInBounds InBounds>
700 : void PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index);
701 :
702 : // If |str| is an index in the range [0, INT32_MAX], return it. If the string
703 : // is not an index in this range, return -1.
704 : int32_t GetIndexFromString(JSString* str);
705 :
706 : JSObject* WrapObjectPure(JSContext* cx, JSObject* obj);
707 :
708 : MOZ_MUST_USE bool
709 : DebugPrologue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn);
710 : MOZ_MUST_USE bool
711 : DebugEpilogue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool ok);
712 : MOZ_MUST_USE bool
713 : DebugEpilogueOnBaselineReturn(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
714 : void FrameIsDebuggeeCheck(BaselineFrame* frame);
715 :
716 : JSObject* CreateGenerator(JSContext* cx, BaselineFrame* frame);
717 :
718 : MOZ_MUST_USE bool
719 : NormalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc,
720 : uint32_t stackDepth);
721 : MOZ_MUST_USE bool
722 : FinalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc);
723 : MOZ_MUST_USE bool
724 : InterpretResume(JSContext* cx, HandleObject obj, HandleValue val, HandlePropertyName kind,
725 : MutableHandleValue rval);
726 : MOZ_MUST_USE bool
727 : DebugAfterYield(JSContext* cx, BaselineFrame* frame);
728 : MOZ_MUST_USE bool
729 : GeneratorThrowOrClose(JSContext* cx, BaselineFrame* frame, Handle<GeneratorObject*> genObj,
730 : HandleValue arg, uint32_t resumeKind);
731 :
732 : MOZ_MUST_USE bool
733 : GlobalNameConflictsCheckFromIon(JSContext* cx, HandleScript script);
734 : MOZ_MUST_USE bool
735 : CheckGlobalOrEvalDeclarationConflicts(JSContext* cx, BaselineFrame* frame);
736 : MOZ_MUST_USE bool
737 : InitFunctionEnvironmentObjects(JSContext* cx, BaselineFrame* frame);
738 :
739 : MOZ_MUST_USE bool
740 : NewArgumentsObject(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
741 :
742 : JSObject* CopyLexicalEnvironmentObject(JSContext* cx, HandleObject env, bool copySlots);
743 :
744 : JSObject* InitRestParameter(JSContext* cx, uint32_t length, Value* rest, HandleObject templateObj,
745 : HandleObject res);
746 :
747 : MOZ_MUST_USE bool
748 : HandleDebugTrap(JSContext* cx, BaselineFrame* frame, uint8_t* retAddr, bool* mustReturn);
749 : MOZ_MUST_USE bool
750 : OnDebuggerStatement(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn);
751 : MOZ_MUST_USE bool
752 : GlobalHasLiveOnDebuggerStatement(JSContext* cx);
753 :
754 : MOZ_MUST_USE bool
755 : EnterWith(JSContext* cx, BaselineFrame* frame, HandleValue val, Handle<WithScope*> templ);
756 : MOZ_MUST_USE bool
757 : LeaveWith(JSContext* cx, BaselineFrame* frame);
758 :
759 : MOZ_MUST_USE bool
760 : PushLexicalEnv(JSContext* cx, BaselineFrame* frame, Handle<LexicalScope*> scope);
761 : MOZ_MUST_USE bool
762 : PopLexicalEnv(JSContext* cx, BaselineFrame* frame);
763 : MOZ_MUST_USE bool
764 : DebugLeaveThenPopLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
765 : MOZ_MUST_USE bool
766 : FreshenLexicalEnv(JSContext* cx, BaselineFrame* frame);
767 : MOZ_MUST_USE bool
768 : DebugLeaveThenFreshenLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
769 : MOZ_MUST_USE bool
770 : RecreateLexicalEnv(JSContext* cx, BaselineFrame* frame);
771 : MOZ_MUST_USE bool
772 : DebugLeaveThenRecreateLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
773 : MOZ_MUST_USE bool
774 : DebugLeaveLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
775 :
776 : MOZ_MUST_USE bool
777 : PushVarEnv(JSContext* cx, BaselineFrame* frame, HandleScope scope);
778 : MOZ_MUST_USE bool
779 : PopVarEnv(JSContext* cx, BaselineFrame* frame);
780 :
781 : MOZ_MUST_USE bool
782 : InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame,
783 : uint32_t numStackValues);
784 :
785 : JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
786 : HandleObject owner, int32_t offset);
787 :
788 : MOZ_MUST_USE bool
789 : Recompile(JSContext* cx);
790 : MOZ_MUST_USE bool
791 : ForcedRecompile(JSContext* cx);
792 : JSString* StringReplace(JSContext* cx, HandleString string, HandleString pattern,
793 : HandleString repl);
794 :
795 : MOZ_MUST_USE bool SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
796 : HandleValue value, bool strict);
797 :
798 : void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
799 : void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj);
800 : void AssertValidStringPtr(JSContext* cx, JSString* str);
801 : void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym);
802 : void AssertValidValue(JSContext* cx, Value* v);
803 :
804 : void MarkValueFromIon(JSRuntime* rt, Value* vp);
805 : void MarkStringFromIon(JSRuntime* rt, JSString** stringp);
806 : void MarkObjectFromIon(JSRuntime* rt, JSObject** objp);
807 : void MarkShapeFromIon(JSRuntime* rt, Shape** shapep);
808 : void MarkObjectGroupFromIon(JSRuntime* rt, ObjectGroup** groupp);
809 :
810 : // Helper for generatePreBarrier.
811 : inline void*
812 20 : IonMarkFunction(MIRType type)
813 : {
814 20 : switch (type) {
815 : case MIRType::Value:
816 4 : return JS_FUNC_TO_DATA_PTR(void*, MarkValueFromIon);
817 : case MIRType::String:
818 4 : return JS_FUNC_TO_DATA_PTR(void*, MarkStringFromIon);
819 : case MIRType::Object:
820 4 : return JS_FUNC_TO_DATA_PTR(void*, MarkObjectFromIon);
821 : case MIRType::Shape:
822 4 : return JS_FUNC_TO_DATA_PTR(void*, MarkShapeFromIon);
823 : case MIRType::ObjectGroup:
824 4 : return JS_FUNC_TO_DATA_PTR(void*, MarkObjectGroupFromIon);
825 0 : default: MOZ_CRASH();
826 : }
827 : }
828 :
829 : bool ObjectIsCallable(JSObject* obj);
830 : bool ObjectIsConstructor(JSObject* obj);
831 :
832 : MOZ_MUST_USE bool
833 : ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber);
834 :
835 : MOZ_MUST_USE bool
836 : ThrowReadOnlyError(JSContext* cx, HandleObject obj, int32_t index);
837 :
838 : MOZ_MUST_USE bool
839 : BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame);
840 :
841 : MOZ_MUST_USE bool
842 : BaselineThrowInitializedThis(JSContext* cx, BaselineFrame* frame);
843 :
844 : MOZ_MUST_USE bool
845 : ThrowBadDerivedReturn(JSContext* cx, HandleValue v);
846 :
847 : MOZ_MUST_USE bool
848 : ThrowObjectCoercible(JSContext* cx, HandleValue v);
849 :
850 : MOZ_MUST_USE bool
851 : BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
852 :
853 : MOZ_MUST_USE bool
854 : CallNativeGetter(JSContext* cx, HandleFunction callee, HandleObject obj,
855 : MutableHandleValue result);
856 :
857 : MOZ_MUST_USE bool
858 : CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj,
859 : HandleValue rhs);
860 :
861 : MOZ_MUST_USE bool
862 : EqualStringsHelper(JSString* str1, JSString* str2);
863 :
864 : MOZ_MUST_USE bool
865 : CheckIsCallable(JSContext* cx, HandleValue v, CheckIsCallableKind kind);
866 :
867 : template <bool HandleMissing>
868 : bool
869 : GetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
870 :
871 : template <bool HandleMissing>
872 : bool
873 : GetNativeDataPropertyByValue(JSContext* cx, JSObject* obj, Value* vp);
874 :
875 : bool
876 : HasOwnNativeDataProperty(JSContext* cx, JSObject* obj, Value* vp);
877 :
878 : template <bool NeedsTypeBarrier>
879 : bool
880 : SetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
881 :
882 : bool
883 : ObjectHasGetterSetter(JSContext* cx, JSObject* obj, Shape* propShape);
884 :
885 : JSString*
886 : TypeOfObject(JSObject* obj, JSRuntime* rt);
887 :
888 : } // namespace jit
889 : } // namespace js
890 :
891 : #endif /* jit_VMFunctions_h */
|