LCOV - code coverage report
Current view: top level - js/src/jit - VMFunctions.h (source / functions) Hit Total Coverage
Test: output.info Lines: 79 89 88.8 %
Date: 2017-07-14 16:53:18 Functions: 1462 1464 99.9 %
Legend: Lines: hit not hit

          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 */

Generated by: LCOV version 1.13