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