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