js/src/jit/VMFunctions.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/VMFunctions.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,706 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_VMFunctions_h
    1.11 +#define jit_VMFunctions_h
    1.12 +
    1.13 +#include "jspubtd.h"
    1.14 +
    1.15 +#include "jit/CompileInfo.h"
    1.16 +#include "jit/IonFrames.h"
    1.17 +
    1.18 +namespace js {
    1.19 +
    1.20 +class DeclEnvObject;
    1.21 +class ForkJoinContext;
    1.22 +class StaticWithObject;
    1.23 +
    1.24 +namespace jit {
    1.25 +
    1.26 +enum DataType {
    1.27 +    Type_Void,
    1.28 +    Type_Bool,
    1.29 +    Type_Int32,
    1.30 +    Type_Double,
    1.31 +    Type_Pointer,
    1.32 +    Type_Object,
    1.33 +    Type_Value,
    1.34 +    Type_Handle
    1.35 +};
    1.36 +
    1.37 +struct PopValues
    1.38 +{
    1.39 +    uint32_t numValues;
    1.40 +
    1.41 +    explicit PopValues(uint32_t numValues)
    1.42 +      : numValues(numValues)
    1.43 +    { }
    1.44 +};
    1.45 +
    1.46 +// Contains information about a virtual machine function that can be called
    1.47 +// from JIT code. Functions described in this manner must conform to a simple
    1.48 +// protocol: the return type must have a special "failure" value (for example,
    1.49 +// false for bool, or nullptr for Objects). If the function is designed to
    1.50 +// return a value that does not meet this requirement - such as
    1.51 +// object-or-nullptr, or an integer, an optional, final outParam can be
    1.52 +// specified. In this case, the return type must be boolean to indicate
    1.53 +// failure.
    1.54 +//
    1.55 +// All functions described by VMFunction take a JSContext * as a first
    1.56 +// argument, and are treated as re-entrant into the VM and therefore fallible.
    1.57 +struct VMFunction
    1.58 +{
    1.59 +    // Global linked list of all VMFunctions.
    1.60 +    static VMFunction *functions;
    1.61 +    VMFunction *next;
    1.62 +
    1.63 +    // Address of the C function.
    1.64 +    void *wrapped;
    1.65 +
    1.66 +    // Number of arguments expected, excluding JSContext * as an implicit
    1.67 +    // first argument and an outparam as a possible implicit final argument.
    1.68 +    uint32_t explicitArgs;
    1.69 +
    1.70 +    enum ArgProperties {
    1.71 +        WordByValue = 0,
    1.72 +        DoubleByValue = 1,
    1.73 +        WordByRef = 2,
    1.74 +        DoubleByRef = 3,
    1.75 +        // BitMask version.
    1.76 +        Word = 0,
    1.77 +        Double = 1,
    1.78 +        ByRef = 2
    1.79 +    };
    1.80 +
    1.81 +    // Contains properties about the first 16 arguments.
    1.82 +    uint32_t argumentProperties;
    1.83 +
    1.84 +    // Which arguments should be passed in float register on platforms that
    1.85 +    // have them.
    1.86 +    uint32_t argumentPassedInFloatRegs;
    1.87 +
    1.88 +    // The outparam may be any Type_*, and must be the final argument to the
    1.89 +    // function, if not Void. outParam != Void implies that the return type
    1.90 +    // has a boolean failure mode.
    1.91 +    DataType outParam;
    1.92 +
    1.93 +    // Type returned by the C function and used by the VMFunction wrapper to
    1.94 +    // check for failures of the C function.  Valid failure/return types are
    1.95 +    // boolean and object pointers which are asserted inside the VMFunction
    1.96 +    // constructor. If the C function use an outparam (!= Type_Void), then
    1.97 +    // the only valid failure/return type is boolean -- object pointers are
    1.98 +    // pointless because the wrapper will only use it to compare it against
    1.99 +    // nullptr before discarding its value.
   1.100 +    DataType returnType;
   1.101 +
   1.102 +    // Note: a maximum of seven root types is supported.
   1.103 +    enum RootType {
   1.104 +        RootNone = 0,
   1.105 +        RootObject,
   1.106 +        RootString,
   1.107 +        RootPropertyName,
   1.108 +        RootFunction,
   1.109 +        RootValue,
   1.110 +        RootCell
   1.111 +    };
   1.112 +
   1.113 +    // Contains an combination of enumerated types used by the gc for marking
   1.114 +    // arguments of the VM wrapper.
   1.115 +    uint64_t argumentRootTypes;
   1.116 +
   1.117 +    // The root type of the out param if outParam == Type_Handle.
   1.118 +    RootType outParamRootType;
   1.119 +
   1.120 +    // Does this function take a ForkJoinContext * or a JSContext *?
   1.121 +    ExecutionMode executionMode;
   1.122 +
   1.123 +    // Number of Values the VM wrapper should pop from the stack when it returns.
   1.124 +    // Used by baseline IC stubs so that they can use tail calls to call the VM
   1.125 +    // wrapper.
   1.126 +    uint32_t extraValuesToPop;
   1.127 +
   1.128 +    uint32_t argc() const {
   1.129 +        // JSContext * + args + (OutParam? *)
   1.130 +        return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1);
   1.131 +    }
   1.132 +
   1.133 +    DataType failType() const {
   1.134 +        return returnType;
   1.135 +    }
   1.136 +
   1.137 +    ArgProperties argProperties(uint32_t explicitArg) const {
   1.138 +        return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3);
   1.139 +    }
   1.140 +
   1.141 +    RootType argRootType(uint32_t explicitArg) const {
   1.142 +        return RootType((argumentRootTypes >> (3 * explicitArg)) & 7);
   1.143 +    }
   1.144 +
   1.145 +    bool argPassedInFloatReg(uint32_t explicitArg) const {
   1.146 +        return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1;
   1.147 +    }
   1.148 +
   1.149 +    // Return the stack size consumed by explicit arguments.
   1.150 +    size_t explicitStackSlots() const {
   1.151 +        size_t stackSlots = explicitArgs;
   1.152 +
   1.153 +        // Fetch all double-word flags of explicit arguments.
   1.154 +        uint32_t n =
   1.155 +            ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
   1.156 +            & 0x55555555                    // = Mask double-size args.
   1.157 +            & argumentProperties;
   1.158 +
   1.159 +        // Add the number of double-word flags. (expect a few loop
   1.160 +        // iteration)
   1.161 +        while (n) {
   1.162 +            stackSlots++;
   1.163 +            n &= n - 1;
   1.164 +        }
   1.165 +        return stackSlots;
   1.166 +    }
   1.167 +
   1.168 +    // Double-size argument which are passed by value are taking the space
   1.169 +    // of 2 C arguments.  This function is used to compute the number of
   1.170 +    // argument expected by the C function.  This is not the same as
   1.171 +    // explicitStackSlots because reference to stack slots may take one less
   1.172 +    // register in the total count.
   1.173 +    size_t explicitArgc() const {
   1.174 +        size_t stackSlots = explicitArgs;
   1.175 +
   1.176 +        // Fetch all explicit arguments.
   1.177 +        uint32_t n =
   1.178 +            ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
   1.179 +            & argumentProperties;
   1.180 +
   1.181 +        // Filter double-size arguments (0x5 = 0b0101) and remove (& ~)
   1.182 +        // arguments passed by reference (0b1010 >> 1 == 0b0101).
   1.183 +        n = (n & 0x55555555) & ~(n >> 1);
   1.184 +
   1.185 +        // Add the number of double-word transfered by value. (expect a few
   1.186 +        // loop iteration)
   1.187 +        while (n) {
   1.188 +            stackSlots++;
   1.189 +            n &= n - 1;
   1.190 +        }
   1.191 +        return stackSlots;
   1.192 +    }
   1.193 +
   1.194 +    VMFunction()
   1.195 +      : wrapped(nullptr),
   1.196 +        explicitArgs(0),
   1.197 +        argumentProperties(0),
   1.198 +        argumentPassedInFloatRegs(0),
   1.199 +        outParam(Type_Void),
   1.200 +        returnType(Type_Void),
   1.201 +        outParamRootType(RootNone),
   1.202 +        executionMode(SequentialExecution),
   1.203 +        extraValuesToPop(0)
   1.204 +    {
   1.205 +    }
   1.206 +
   1.207 +
   1.208 +    VMFunction(void *wrapped, uint32_t explicitArgs, uint32_t argumentProperties,
   1.209 +               uint32_t argumentPassedInFloatRegs, uint64_t argRootTypes,
   1.210 +               DataType outParam, RootType outParamRootType, DataType returnType,
   1.211 +               ExecutionMode executionMode, uint32_t extraValuesToPop = 0)
   1.212 +      : wrapped(wrapped),
   1.213 +        explicitArgs(explicitArgs),
   1.214 +        argumentProperties(argumentProperties),
   1.215 +        argumentPassedInFloatRegs(argumentPassedInFloatRegs),
   1.216 +        outParam(outParam),
   1.217 +        returnType(returnType),
   1.218 +        argumentRootTypes(argRootTypes),
   1.219 +        outParamRootType(outParamRootType),
   1.220 +        executionMode(executionMode),
   1.221 +        extraValuesToPop(extraValuesToPop)
   1.222 +    {
   1.223 +        // Check for valid failure/return type.
   1.224 +        JS_ASSERT_IF(outParam != Type_Void && executionMode == SequentialExecution,
   1.225 +                     returnType == Type_Bool);
   1.226 +        JS_ASSERT(returnType == Type_Bool ||
   1.227 +                  returnType == Type_Object);
   1.228 +    }
   1.229 +
   1.230 +    VMFunction(const VMFunction &o) {
   1.231 +        init(o);
   1.232 +    }
   1.233 +
   1.234 +    void init(const VMFunction &o) {
   1.235 +        JS_ASSERT(!wrapped);
   1.236 +        *this = o;
   1.237 +        addToFunctions();
   1.238 +    }
   1.239 +
   1.240 +  private:
   1.241 +    // Add this to the global list of VMFunctions.
   1.242 +    void addToFunctions();
   1.243 +};
   1.244 +
   1.245 +// A collection of VM functions for each execution mode.
   1.246 +struct VMFunctionsModal
   1.247 +{
   1.248 +    VMFunctionsModal(const VMFunction &info) {
   1.249 +        add(info);
   1.250 +    }
   1.251 +    VMFunctionsModal(const VMFunction &info1, const VMFunction &info2) {
   1.252 +        add(info1);
   1.253 +        add(info2);
   1.254 +    }
   1.255 +
   1.256 +    inline const VMFunction &operator[](ExecutionMode mode) const {
   1.257 +        JS_ASSERT((unsigned)mode < NumExecutionModes);
   1.258 +        return funs_[mode];
   1.259 +    }
   1.260 +
   1.261 +  private:
   1.262 +    void add(const VMFunction &info) {
   1.263 +        JS_ASSERT((unsigned)info.executionMode < NumExecutionModes);
   1.264 +        funs_[info.executionMode].init(info);
   1.265 +    }
   1.266 +
   1.267 +    mozilla::Array<VMFunction, NumExecutionModes> funs_;
   1.268 +};
   1.269 +
   1.270 +template <class> struct TypeToDataType { /* Unexpected return type for a VMFunction. */ };
   1.271 +template <> struct TypeToDataType<bool> { static const DataType result = Type_Bool; };
   1.272 +template <> struct TypeToDataType<JSObject *> { static const DataType result = Type_Object; };
   1.273 +template <> struct TypeToDataType<DeclEnvObject *> { static const DataType result = Type_Object; };
   1.274 +template <> struct TypeToDataType<JSString *> { static const DataType result = Type_Object; };
   1.275 +template <> struct TypeToDataType<JSFlatString *> { static const DataType result = Type_Object; };
   1.276 +template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
   1.277 +template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; };
   1.278 +template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; };
   1.279 +template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; };
   1.280 +template <> struct TypeToDataType<Handle<StaticWithObject *> > { static const DataType result = Type_Handle; };
   1.281 +template <> struct TypeToDataType<Handle<StaticBlockObject *> > { static const DataType result = Type_Handle; };
   1.282 +template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; };
   1.283 +template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; };
   1.284 +template <> struct TypeToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
   1.285 +
   1.286 +// Convert argument types to properties of the argument known by the jit.
   1.287 +template <class T> struct TypeToArgProperties {
   1.288 +    static const uint32_t result =
   1.289 +        (sizeof(T) <= sizeof(void *) ? VMFunction::Word : VMFunction::Double);
   1.290 +};
   1.291 +template <> struct TypeToArgProperties<const Value &> {
   1.292 +    static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
   1.293 +};
   1.294 +template <> struct TypeToArgProperties<HandleObject> {
   1.295 +    static const uint32_t result = TypeToArgProperties<JSObject *>::result | VMFunction::ByRef;
   1.296 +};
   1.297 +template <> struct TypeToArgProperties<HandleString> {
   1.298 +    static const uint32_t result = TypeToArgProperties<JSString *>::result | VMFunction::ByRef;
   1.299 +};
   1.300 +template <> struct TypeToArgProperties<HandlePropertyName> {
   1.301 +    static const uint32_t result = TypeToArgProperties<PropertyName *>::result | VMFunction::ByRef;
   1.302 +};
   1.303 +template <> struct TypeToArgProperties<HandleFunction> {
   1.304 +    static const uint32_t result = TypeToArgProperties<JSFunction *>::result | VMFunction::ByRef;
   1.305 +};
   1.306 +template <> struct TypeToArgProperties<Handle<StaticWithObject *> > {
   1.307 +    static const uint32_t result = TypeToArgProperties<StaticWithObject *>::result | VMFunction::ByRef;
   1.308 +};
   1.309 +template <> struct TypeToArgProperties<Handle<StaticBlockObject *> > {
   1.310 +    static const uint32_t result = TypeToArgProperties<StaticBlockObject *>::result | VMFunction::ByRef;
   1.311 +};
   1.312 +template <> struct TypeToArgProperties<HandleScript> {
   1.313 +    static const uint32_t result = TypeToArgProperties<JSScript *>::result | VMFunction::ByRef;
   1.314 +};
   1.315 +template <> struct TypeToArgProperties<HandleValue> {
   1.316 +    static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
   1.317 +};
   1.318 +template <> struct TypeToArgProperties<MutableHandleValue> {
   1.319 +    static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
   1.320 +};
   1.321 +template <> struct TypeToArgProperties<HandleShape> {
   1.322 +    static const uint32_t result = TypeToArgProperties<Shape *>::result | VMFunction::ByRef;
   1.323 +};
   1.324 +template <> struct TypeToArgProperties<HandleTypeObject> {
   1.325 +    static const uint32_t result = TypeToArgProperties<types::TypeObject *>::result | VMFunction::ByRef;
   1.326 +};
   1.327 +
   1.328 +// Convert argument type to whether or not it should be passed in a float
   1.329 +// register on platforms that have them, like x64.
   1.330 +template <class T> struct TypeToPassInFloatReg {
   1.331 +    static const uint32_t result = 0;
   1.332 +};
   1.333 +template <> struct TypeToPassInFloatReg<double> {
   1.334 +    static const uint32_t result = 1;
   1.335 +};
   1.336 +
   1.337 +// Convert argument types to root types used by the gc, see MarkJitExitFrame.
   1.338 +template <class T> struct TypeToRootType {
   1.339 +    static const uint32_t result = VMFunction::RootNone;
   1.340 +};
   1.341 +template <> struct TypeToRootType<HandleObject> {
   1.342 +    static const uint32_t result = VMFunction::RootObject;
   1.343 +};
   1.344 +template <> struct TypeToRootType<HandleString> {
   1.345 +    static const uint32_t result = VMFunction::RootString;
   1.346 +};
   1.347 +template <> struct TypeToRootType<HandlePropertyName> {
   1.348 +    static const uint32_t result = VMFunction::RootPropertyName;
   1.349 +};
   1.350 +template <> struct TypeToRootType<HandleFunction> {
   1.351 +    static const uint32_t result = VMFunction::RootFunction;
   1.352 +};
   1.353 +template <> struct TypeToRootType<HandleValue> {
   1.354 +    static const uint32_t result = VMFunction::RootValue;
   1.355 +};
   1.356 +template <> struct TypeToRootType<MutableHandleValue> {
   1.357 +    static const uint32_t result = VMFunction::RootValue;
   1.358 +};
   1.359 +template <> struct TypeToRootType<HandleShape> {
   1.360 +    static const uint32_t result = VMFunction::RootCell;
   1.361 +};
   1.362 +template <> struct TypeToRootType<HandleTypeObject> {
   1.363 +    static const uint32_t result = VMFunction::RootCell;
   1.364 +};
   1.365 +template <> struct TypeToRootType<HandleScript> {
   1.366 +    static const uint32_t result = VMFunction::RootCell;
   1.367 +};
   1.368 +template <> struct TypeToRootType<Handle<StaticBlockObject *> > {
   1.369 +    static const uint32_t result = VMFunction::RootObject;
   1.370 +};
   1.371 +template <> struct TypeToRootType<Handle<StaticWithObject *> > {
   1.372 +    static const uint32_t result = VMFunction::RootCell;
   1.373 +};
   1.374 +template <class T> struct TypeToRootType<Handle<T> > {
   1.375 +    // Fail for Handle types that aren't specialized above.
   1.376 +};
   1.377 +
   1.378 +template <class> struct OutParamToDataType { static const DataType result = Type_Void; };
   1.379 +template <> struct OutParamToDataType<Value *> { static const DataType result = Type_Value; };
   1.380 +template <> struct OutParamToDataType<int *> { static const DataType result = Type_Int32; };
   1.381 +template <> struct OutParamToDataType<uint32_t *> { static const DataType result = Type_Int32; };
   1.382 +template <> struct OutParamToDataType<uint8_t **> { static const DataType result = Type_Pointer; };
   1.383 +template <> struct OutParamToDataType<bool *> { static const DataType result = Type_Bool; };
   1.384 +template <> struct OutParamToDataType<double *> { static const DataType result = Type_Double; };
   1.385 +template <> struct OutParamToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
   1.386 +template <> struct OutParamToDataType<MutableHandleObject> { static const DataType result = Type_Handle; };
   1.387 +template <> struct OutParamToDataType<MutableHandleString> { static const DataType result = Type_Handle; };
   1.388 +
   1.389 +template <class> struct OutParamToRootType {
   1.390 +    static const VMFunction::RootType result = VMFunction::RootNone;
   1.391 +};
   1.392 +template <> struct OutParamToRootType<MutableHandleValue> {
   1.393 +    static const VMFunction::RootType result = VMFunction::RootValue;
   1.394 +};
   1.395 +template <> struct OutParamToRootType<MutableHandleObject> {
   1.396 +    static const VMFunction::RootType result = VMFunction::RootObject;
   1.397 +};
   1.398 +template <> struct OutParamToRootType<MutableHandleString> {
   1.399 +    static const VMFunction::RootType result = VMFunction::RootString;
   1.400 +};
   1.401 +
   1.402 +template <class> struct MatchContext { };
   1.403 +template <> struct MatchContext<JSContext *> {
   1.404 +    static const ExecutionMode execMode = SequentialExecution;
   1.405 +};
   1.406 +template <> struct MatchContext<ExclusiveContext *> {
   1.407 +    static const ExecutionMode execMode = SequentialExecution;
   1.408 +};
   1.409 +template <> struct MatchContext<ForkJoinContext *> {
   1.410 +    static const ExecutionMode execMode = ParallelExecution;
   1.411 +};
   1.412 +template <> struct MatchContext<ThreadSafeContext *> {
   1.413 +    // ThreadSafeContext functions can be called from either mode, but for
   1.414 +    // calling from parallel they should be wrapped first, so we default to
   1.415 +    // SequentialExecution here.
   1.416 +    static const ExecutionMode execMode = SequentialExecution;
   1.417 +};
   1.418 +
   1.419 +#define FOR_EACH_ARGS_1(Macro, Sep, Last) Macro(1) Last(1)
   1.420 +#define FOR_EACH_ARGS_2(Macro, Sep, Last) FOR_EACH_ARGS_1(Macro, Sep, Sep) Macro(2) Last(2)
   1.421 +#define FOR_EACH_ARGS_3(Macro, Sep, Last) FOR_EACH_ARGS_2(Macro, Sep, Sep) Macro(3) Last(3)
   1.422 +#define FOR_EACH_ARGS_4(Macro, Sep, Last) FOR_EACH_ARGS_3(Macro, Sep, Sep) Macro(4) Last(4)
   1.423 +#define FOR_EACH_ARGS_5(Macro, Sep, Last) FOR_EACH_ARGS_4(Macro, Sep, Sep) Macro(5) Last(5)
   1.424 +#define FOR_EACH_ARGS_6(Macro, Sep, Last) FOR_EACH_ARGS_5(Macro, Sep, Sep) Macro(6) Last(6)
   1.425 +
   1.426 +#define COMPUTE_INDEX(NbArg) NbArg
   1.427 +#define COMPUTE_OUTPARAM_RESULT(NbArg) OutParamToDataType<A ## NbArg>::result
   1.428 +#define COMPUTE_OUTPARAM_ROOT(NbArg) OutParamToRootType<A ## NbArg>::result
   1.429 +#define COMPUTE_ARG_PROP(NbArg) (TypeToArgProperties<A ## NbArg>::result << (2 * (NbArg - 1)))
   1.430 +#define COMPUTE_ARG_ROOT(NbArg) (uint64_t(TypeToRootType<A ## NbArg>::result) << (3 * (NbArg - 1)))
   1.431 +#define COMPUTE_ARG_FLOAT(NbArg) (TypeToPassInFloatReg<A ## NbArg>::result) << (NbArg - 1)
   1.432 +#define SEP_OR(_) |
   1.433 +#define NOTHING(_)
   1.434 +
   1.435 +#define FUNCTION_INFO_STRUCT_BODY(ForEachNb)                                            \
   1.436 +    static inline ExecutionMode executionMode() {                                       \
   1.437 +        return MatchContext<Context>::execMode;                                         \
   1.438 +    }                                                                                   \
   1.439 +    static inline DataType returnType() {                                               \
   1.440 +        return TypeToDataType<R>::result;                                               \
   1.441 +    }                                                                                   \
   1.442 +    static inline DataType outParam() {                                                 \
   1.443 +        return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_RESULT);                    \
   1.444 +    }                                                                                   \
   1.445 +    static inline RootType outParamRootType() {                                         \
   1.446 +        return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_ROOT);                      \
   1.447 +    }                                                                                   \
   1.448 +    static inline size_t NbArgs() {                                                     \
   1.449 +        return ForEachNb(NOTHING, NOTHING, COMPUTE_INDEX);                              \
   1.450 +    }                                                                                   \
   1.451 +    static inline size_t explicitArgs() {                                               \
   1.452 +        return NbArgs() - (outParam() != Type_Void ? 1 : 0);                            \
   1.453 +    }                                                                                   \
   1.454 +    static inline uint32_t argumentProperties() {                                       \
   1.455 +        return ForEachNb(COMPUTE_ARG_PROP, SEP_OR, NOTHING);                            \
   1.456 +    }                                                                                   \
   1.457 +    static inline uint32_t argumentPassedInFloatRegs() {                                \
   1.458 +        return ForEachNb(COMPUTE_ARG_FLOAT, SEP_OR, NOTHING);                           \
   1.459 +    }                                                                                   \
   1.460 +    static inline uint64_t argumentRootTypes() {                                        \
   1.461 +        return ForEachNb(COMPUTE_ARG_ROOT, SEP_OR, NOTHING);                            \
   1.462 +    }                                                                                   \
   1.463 +    FunctionInfo(pf fun, PopValues extraValuesToPop = PopValues(0))                     \
   1.464 +        : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(),                  \
   1.465 +                     argumentProperties(), argumentPassedInFloatRegs(),                 \
   1.466 +                     argumentRootTypes(), outParam(), outParamRootType(),               \
   1.467 +                     returnType(), executionMode(),                                     \
   1.468 +                     extraValuesToPop.numValues)                                        \
   1.469 +    { }
   1.470 +
   1.471 +template <typename Fun>
   1.472 +struct FunctionInfo {
   1.473 +};
   1.474 +
   1.475 +// VMFunction wrapper with no explicit arguments.
   1.476 +template <class R, class Context>
   1.477 +struct FunctionInfo<R (*)(Context)> : public VMFunction {
   1.478 +    typedef R (*pf)(Context);
   1.479 +
   1.480 +    static inline ExecutionMode executionMode() {
   1.481 +        return MatchContext<Context>::execMode;
   1.482 +    }
   1.483 +    static inline DataType returnType() {
   1.484 +        return TypeToDataType<R>::result;
   1.485 +    }
   1.486 +    static inline DataType outParam() {
   1.487 +        return Type_Void;
   1.488 +    }
   1.489 +    static inline RootType outParamRootType() {
   1.490 +        return RootNone;
   1.491 +    }
   1.492 +    static inline size_t explicitArgs() {
   1.493 +        return 0;
   1.494 +    }
   1.495 +    static inline uint32_t argumentProperties() {
   1.496 +        return 0;
   1.497 +    }
   1.498 +    static inline uint32_t argumentPassedInFloatRegs() {
   1.499 +        return 0;
   1.500 +    }
   1.501 +    static inline uint64_t argumentRootTypes() {
   1.502 +        return 0;
   1.503 +    }
   1.504 +    FunctionInfo(pf fun)
   1.505 +      : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(),
   1.506 +                   argumentProperties(), argumentPassedInFloatRegs(),
   1.507 +                   argumentRootTypes(), outParam(), outParamRootType(),
   1.508 +                   returnType(), executionMode())
   1.509 +    { }
   1.510 +};
   1.511 +
   1.512 +// Specialize the class for each number of argument used by VMFunction.
   1.513 +// Keep it verbose unless you find a readable macro for it.
   1.514 +template <class R, class Context, class A1>
   1.515 +struct FunctionInfo<R (*)(Context, A1)> : public VMFunction {
   1.516 +    typedef R (*pf)(Context, A1);
   1.517 +    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1)
   1.518 +};
   1.519 +
   1.520 +template <class R, class Context, class A1, class A2>
   1.521 +struct FunctionInfo<R (*)(Context, A1, A2)> : public VMFunction {
   1.522 +    typedef R (*pf)(Context, A1, A2);
   1.523 +    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2)
   1.524 +};
   1.525 +
   1.526 +template <class R, class Context, class A1, class A2, class A3>
   1.527 +struct FunctionInfo<R (*)(Context, A1, A2, A3)> : public VMFunction {
   1.528 +    typedef R (*pf)(Context, A1, A2, A3);
   1.529 +    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3)
   1.530 +};
   1.531 +
   1.532 +template <class R, class Context, class A1, class A2, class A3, class A4>
   1.533 +struct FunctionInfo<R (*)(Context, A1, A2, A3, A4)> : public VMFunction {
   1.534 +    typedef R (*pf)(Context, A1, A2, A3, A4);
   1.535 +    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4)
   1.536 +};
   1.537 +
   1.538 +template <class R, class Context, class A1, class A2, class A3, class A4, class A5>
   1.539 +    struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5)> : public VMFunction {
   1.540 +    typedef R (*pf)(Context, A1, A2, A3, A4, A5);
   1.541 +    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5)
   1.542 +};
   1.543 +
   1.544 +template <class R, class Context, class A1, class A2, class A3, class A4, class A5, class A6>
   1.545 +    struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5, A6)> : public VMFunction {
   1.546 +    typedef R (*pf)(Context, A1, A2, A3, A4, A5, A6);
   1.547 +    FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_6)
   1.548 +};
   1.549 +
   1.550 +#undef FUNCTION_INFO_STRUCT_BODY
   1.551 +
   1.552 +#undef FOR_EACH_ARGS_6
   1.553 +#undef FOR_EACH_ARGS_5
   1.554 +#undef FOR_EACH_ARGS_4
   1.555 +#undef FOR_EACH_ARGS_3
   1.556 +#undef FOR_EACH_ARGS_2
   1.557 +#undef FOR_EACH_ARGS_1
   1.558 +
   1.559 +#undef COMPUTE_INDEX
   1.560 +#undef COMPUTE_OUTPARAM_RESULT
   1.561 +#undef COMPUTE_OUTPARAM_ROOT
   1.562 +#undef COMPUTE_ARG_PROP
   1.563 +#undef COMPUTE_ARG_FLOAT
   1.564 +#undef SEP_OR
   1.565 +#undef NOTHING
   1.566 +
   1.567 +class AutoDetectInvalidation
   1.568 +{
   1.569 +    JSContext *cx_;
   1.570 +    IonScript *ionScript_;
   1.571 +    Value *rval_;
   1.572 +    bool disabled_;
   1.573 +
   1.574 +  public:
   1.575 +    AutoDetectInvalidation(JSContext *cx, Value *rval, IonScript *ionScript = nullptr);
   1.576 +
   1.577 +    void disable() {
   1.578 +        JS_ASSERT(!disabled_);
   1.579 +        disabled_ = true;
   1.580 +    }
   1.581 +
   1.582 +    ~AutoDetectInvalidation() {
   1.583 +        if (!disabled_ && ionScript_->invalidated())
   1.584 +            cx_->runtime()->setIonReturnOverride(*rval_);
   1.585 +    }
   1.586 +};
   1.587 +
   1.588 +bool InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Value *rval);
   1.589 +JSObject *NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap);
   1.590 +
   1.591 +bool CheckOverRecursed(JSContext *cx);
   1.592 +bool CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame,
   1.593 +                                uint32_t extra, uint32_t earlyCheck);
   1.594 +
   1.595 +bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
   1.596 +bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval);
   1.597 +bool MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value);
   1.598 +bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
   1.599 +
   1.600 +template<bool Equal>
   1.601 +bool LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
   1.602 +
   1.603 +template<bool Equal>
   1.604 +bool StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
   1.605 +
   1.606 +bool LessThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
   1.607 +bool LessThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
   1.608 +bool GreaterThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
   1.609 +bool GreaterThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
   1.610 +
   1.611 +template<bool Equal>
   1.612 +bool StringsEqual(JSContext *cx, HandleString left, HandleString right, bool *res);
   1.613 +
   1.614 +bool IteratorMore(JSContext *cx, HandleObject obj, bool *res);
   1.615 +
   1.616 +// Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT and parallel array inlining
   1.617 +JSObject *NewInitParallelArray(JSContext *cx, HandleObject templateObj);
   1.618 +JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type);
   1.619 +JSObject *NewInitObject(JSContext *cx, HandleObject templateObject);
   1.620 +JSObject *NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject);
   1.621 +
   1.622 +bool ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval);
   1.623 +bool ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length);
   1.624 +bool ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval);
   1.625 +JSObject *ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject res);
   1.626 +
   1.627 +bool CharCodeAt(JSContext *cx, HandleString str, int32_t index, uint32_t *code);
   1.628 +JSFlatString *StringFromCharCode(JSContext *cx, int32_t code);
   1.629 +
   1.630 +bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
   1.631 +                 bool strict, jsbytecode *pc);
   1.632 +
   1.633 +bool InterruptCheck(JSContext *cx);
   1.634 +
   1.635 +HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots);
   1.636 +JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
   1.637 +JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots);
   1.638 +JSObject *NewStringObject(JSContext *cx, HandleString str);
   1.639 +
   1.640 +bool SPSEnter(JSContext *cx, HandleScript script);
   1.641 +bool SPSExit(JSContext *cx, HandleScript script);
   1.642 +
   1.643 +bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, bool *out);
   1.644 +bool OperatorInI(JSContext *cx, uint32_t index, HandleObject obj, bool *out);
   1.645 +
   1.646 +bool GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rval);
   1.647 +
   1.648 +bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval);
   1.649 +
   1.650 +void GetDynamicName(JSContext *cx, JSObject *scopeChain, JSString *str, Value *vp);
   1.651 +
   1.652 +bool FilterArgumentsOrEval(JSContext *cx, JSString *str);
   1.653 +
   1.654 +#ifdef JSGC_GENERATIONAL
   1.655 +void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
   1.656 +void PostGlobalWriteBarrier(JSRuntime *rt, JSObject *obj);
   1.657 +#endif
   1.658 +
   1.659 +uint32_t GetIndexFromString(JSString *str);
   1.660 +
   1.661 +bool DebugPrologue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn);
   1.662 +bool DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok);
   1.663 +
   1.664 +bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame);
   1.665 +bool HeavyweightFunPrologue(JSContext *cx, BaselineFrame *frame);
   1.666 +
   1.667 +bool NewArgumentsObject(JSContext *cx, BaselineFrame *frame, MutableHandleValue res);
   1.668 +
   1.669 +JSObject *InitRestParameter(JSContext *cx, uint32_t length, Value *rest, HandleObject templateObj,
   1.670 +                            HandleObject res);
   1.671 +
   1.672 +bool HandleDebugTrap(JSContext *cx, BaselineFrame *frame, uint8_t *retAddr, bool *mustReturn);
   1.673 +bool OnDebuggerStatement(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn);
   1.674 +
   1.675 +bool EnterWith(JSContext *cx, BaselineFrame *frame, HandleValue val,
   1.676 +               Handle<StaticWithObject *> templ);
   1.677 +bool LeaveWith(JSContext *cx, BaselineFrame *frame);
   1.678 +
   1.679 +bool PushBlockScope(JSContext *cx, BaselineFrame *frame, Handle<StaticBlockObject *> block);
   1.680 +bool PopBlockScope(JSContext *cx, BaselineFrame *frame);
   1.681 +bool DebugLeaveBlock(JSContext *cx, BaselineFrame *frame, jsbytecode *pc);
   1.682 +
   1.683 +bool InitBaselineFrameForOsr(BaselineFrame *frame, InterpreterFrame *interpFrame,
   1.684 +                             uint32_t numStackValues);
   1.685 +
   1.686 +JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject descr,
   1.687 +                                HandleObject owner, int32_t offset);
   1.688 +
   1.689 +bool ArraySpliceDense(JSContext *cx, HandleObject obj, uint32_t start, uint32_t deleteCount);
   1.690 +
   1.691 +bool Recompile(JSContext *cx);
   1.692 +JSString *RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp,
   1.693 +                        HandleString repl);
   1.694 +JSString *StringReplace(JSContext *cx, HandleString string, HandleString pattern,
   1.695 +                        HandleString repl);
   1.696 +
   1.697 +bool SetDenseElement(JSContext *cx, HandleObject obj, int32_t index, HandleValue value,
   1.698 +                     bool strict);
   1.699 +
   1.700 +#ifdef DEBUG
   1.701 +void AssertValidObjectPtr(JSContext *cx, JSObject *obj);
   1.702 +void AssertValidStringPtr(JSContext *cx, JSString *str);
   1.703 +void AssertValidValue(JSContext *cx, Value *v);
   1.704 +#endif
   1.705 +
   1.706 +} // namespace jit
   1.707 +} // namespace js
   1.708 +
   1.709 +#endif /* jit_VMFunctions_h */

mercurial