js/src/jit/VMFunctions.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jit_VMFunctions_h
michael@0 8 #define jit_VMFunctions_h
michael@0 9
michael@0 10 #include "jspubtd.h"
michael@0 11
michael@0 12 #include "jit/CompileInfo.h"
michael@0 13 #include "jit/IonFrames.h"
michael@0 14
michael@0 15 namespace js {
michael@0 16
michael@0 17 class DeclEnvObject;
michael@0 18 class ForkJoinContext;
michael@0 19 class StaticWithObject;
michael@0 20
michael@0 21 namespace jit {
michael@0 22
michael@0 23 enum DataType {
michael@0 24 Type_Void,
michael@0 25 Type_Bool,
michael@0 26 Type_Int32,
michael@0 27 Type_Double,
michael@0 28 Type_Pointer,
michael@0 29 Type_Object,
michael@0 30 Type_Value,
michael@0 31 Type_Handle
michael@0 32 };
michael@0 33
michael@0 34 struct PopValues
michael@0 35 {
michael@0 36 uint32_t numValues;
michael@0 37
michael@0 38 explicit PopValues(uint32_t numValues)
michael@0 39 : numValues(numValues)
michael@0 40 { }
michael@0 41 };
michael@0 42
michael@0 43 // Contains information about a virtual machine function that can be called
michael@0 44 // from JIT code. Functions described in this manner must conform to a simple
michael@0 45 // protocol: the return type must have a special "failure" value (for example,
michael@0 46 // false for bool, or nullptr for Objects). If the function is designed to
michael@0 47 // return a value that does not meet this requirement - such as
michael@0 48 // object-or-nullptr, or an integer, an optional, final outParam can be
michael@0 49 // specified. In this case, the return type must be boolean to indicate
michael@0 50 // failure.
michael@0 51 //
michael@0 52 // All functions described by VMFunction take a JSContext * as a first
michael@0 53 // argument, and are treated as re-entrant into the VM and therefore fallible.
michael@0 54 struct VMFunction
michael@0 55 {
michael@0 56 // Global linked list of all VMFunctions.
michael@0 57 static VMFunction *functions;
michael@0 58 VMFunction *next;
michael@0 59
michael@0 60 // Address of the C function.
michael@0 61 void *wrapped;
michael@0 62
michael@0 63 // Number of arguments expected, excluding JSContext * as an implicit
michael@0 64 // first argument and an outparam as a possible implicit final argument.
michael@0 65 uint32_t explicitArgs;
michael@0 66
michael@0 67 enum ArgProperties {
michael@0 68 WordByValue = 0,
michael@0 69 DoubleByValue = 1,
michael@0 70 WordByRef = 2,
michael@0 71 DoubleByRef = 3,
michael@0 72 // BitMask version.
michael@0 73 Word = 0,
michael@0 74 Double = 1,
michael@0 75 ByRef = 2
michael@0 76 };
michael@0 77
michael@0 78 // Contains properties about the first 16 arguments.
michael@0 79 uint32_t argumentProperties;
michael@0 80
michael@0 81 // Which arguments should be passed in float register on platforms that
michael@0 82 // have them.
michael@0 83 uint32_t argumentPassedInFloatRegs;
michael@0 84
michael@0 85 // The outparam may be any Type_*, and must be the final argument to the
michael@0 86 // function, if not Void. outParam != Void implies that the return type
michael@0 87 // has a boolean failure mode.
michael@0 88 DataType outParam;
michael@0 89
michael@0 90 // Type returned by the C function and used by the VMFunction wrapper to
michael@0 91 // check for failures of the C function. Valid failure/return types are
michael@0 92 // boolean and object pointers which are asserted inside the VMFunction
michael@0 93 // constructor. If the C function use an outparam (!= Type_Void), then
michael@0 94 // the only valid failure/return type is boolean -- object pointers are
michael@0 95 // pointless because the wrapper will only use it to compare it against
michael@0 96 // nullptr before discarding its value.
michael@0 97 DataType returnType;
michael@0 98
michael@0 99 // Note: a maximum of seven root types is supported.
michael@0 100 enum RootType {
michael@0 101 RootNone = 0,
michael@0 102 RootObject,
michael@0 103 RootString,
michael@0 104 RootPropertyName,
michael@0 105 RootFunction,
michael@0 106 RootValue,
michael@0 107 RootCell
michael@0 108 };
michael@0 109
michael@0 110 // Contains an combination of enumerated types used by the gc for marking
michael@0 111 // arguments of the VM wrapper.
michael@0 112 uint64_t argumentRootTypes;
michael@0 113
michael@0 114 // The root type of the out param if outParam == Type_Handle.
michael@0 115 RootType outParamRootType;
michael@0 116
michael@0 117 // Does this function take a ForkJoinContext * or a JSContext *?
michael@0 118 ExecutionMode executionMode;
michael@0 119
michael@0 120 // Number of Values the VM wrapper should pop from the stack when it returns.
michael@0 121 // Used by baseline IC stubs so that they can use tail calls to call the VM
michael@0 122 // wrapper.
michael@0 123 uint32_t extraValuesToPop;
michael@0 124
michael@0 125 uint32_t argc() const {
michael@0 126 // JSContext * + args + (OutParam? *)
michael@0 127 return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1);
michael@0 128 }
michael@0 129
michael@0 130 DataType failType() const {
michael@0 131 return returnType;
michael@0 132 }
michael@0 133
michael@0 134 ArgProperties argProperties(uint32_t explicitArg) const {
michael@0 135 return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3);
michael@0 136 }
michael@0 137
michael@0 138 RootType argRootType(uint32_t explicitArg) const {
michael@0 139 return RootType((argumentRootTypes >> (3 * explicitArg)) & 7);
michael@0 140 }
michael@0 141
michael@0 142 bool argPassedInFloatReg(uint32_t explicitArg) const {
michael@0 143 return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1;
michael@0 144 }
michael@0 145
michael@0 146 // Return the stack size consumed by explicit arguments.
michael@0 147 size_t explicitStackSlots() const {
michael@0 148 size_t stackSlots = explicitArgs;
michael@0 149
michael@0 150 // Fetch all double-word flags of explicit arguments.
michael@0 151 uint32_t n =
michael@0 152 ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
michael@0 153 & 0x55555555 // = Mask double-size args.
michael@0 154 & argumentProperties;
michael@0 155
michael@0 156 // Add the number of double-word flags. (expect a few loop
michael@0 157 // iteration)
michael@0 158 while (n) {
michael@0 159 stackSlots++;
michael@0 160 n &= n - 1;
michael@0 161 }
michael@0 162 return stackSlots;
michael@0 163 }
michael@0 164
michael@0 165 // Double-size argument which are passed by value are taking the space
michael@0 166 // of 2 C arguments. This function is used to compute the number of
michael@0 167 // argument expected by the C function. This is not the same as
michael@0 168 // explicitStackSlots because reference to stack slots may take one less
michael@0 169 // register in the total count.
michael@0 170 size_t explicitArgc() const {
michael@0 171 size_t stackSlots = explicitArgs;
michael@0 172
michael@0 173 // Fetch all explicit arguments.
michael@0 174 uint32_t n =
michael@0 175 ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask.
michael@0 176 & argumentProperties;
michael@0 177
michael@0 178 // Filter double-size arguments (0x5 = 0b0101) and remove (& ~)
michael@0 179 // arguments passed by reference (0b1010 >> 1 == 0b0101).
michael@0 180 n = (n & 0x55555555) & ~(n >> 1);
michael@0 181
michael@0 182 // Add the number of double-word transfered by value. (expect a few
michael@0 183 // loop iteration)
michael@0 184 while (n) {
michael@0 185 stackSlots++;
michael@0 186 n &= n - 1;
michael@0 187 }
michael@0 188 return stackSlots;
michael@0 189 }
michael@0 190
michael@0 191 VMFunction()
michael@0 192 : wrapped(nullptr),
michael@0 193 explicitArgs(0),
michael@0 194 argumentProperties(0),
michael@0 195 argumentPassedInFloatRegs(0),
michael@0 196 outParam(Type_Void),
michael@0 197 returnType(Type_Void),
michael@0 198 outParamRootType(RootNone),
michael@0 199 executionMode(SequentialExecution),
michael@0 200 extraValuesToPop(0)
michael@0 201 {
michael@0 202 }
michael@0 203
michael@0 204
michael@0 205 VMFunction(void *wrapped, uint32_t explicitArgs, uint32_t argumentProperties,
michael@0 206 uint32_t argumentPassedInFloatRegs, uint64_t argRootTypes,
michael@0 207 DataType outParam, RootType outParamRootType, DataType returnType,
michael@0 208 ExecutionMode executionMode, uint32_t extraValuesToPop = 0)
michael@0 209 : wrapped(wrapped),
michael@0 210 explicitArgs(explicitArgs),
michael@0 211 argumentProperties(argumentProperties),
michael@0 212 argumentPassedInFloatRegs(argumentPassedInFloatRegs),
michael@0 213 outParam(outParam),
michael@0 214 returnType(returnType),
michael@0 215 argumentRootTypes(argRootTypes),
michael@0 216 outParamRootType(outParamRootType),
michael@0 217 executionMode(executionMode),
michael@0 218 extraValuesToPop(extraValuesToPop)
michael@0 219 {
michael@0 220 // Check for valid failure/return type.
michael@0 221 JS_ASSERT_IF(outParam != Type_Void && executionMode == SequentialExecution,
michael@0 222 returnType == Type_Bool);
michael@0 223 JS_ASSERT(returnType == Type_Bool ||
michael@0 224 returnType == Type_Object);
michael@0 225 }
michael@0 226
michael@0 227 VMFunction(const VMFunction &o) {
michael@0 228 init(o);
michael@0 229 }
michael@0 230
michael@0 231 void init(const VMFunction &o) {
michael@0 232 JS_ASSERT(!wrapped);
michael@0 233 *this = o;
michael@0 234 addToFunctions();
michael@0 235 }
michael@0 236
michael@0 237 private:
michael@0 238 // Add this to the global list of VMFunctions.
michael@0 239 void addToFunctions();
michael@0 240 };
michael@0 241
michael@0 242 // A collection of VM functions for each execution mode.
michael@0 243 struct VMFunctionsModal
michael@0 244 {
michael@0 245 VMFunctionsModal(const VMFunction &info) {
michael@0 246 add(info);
michael@0 247 }
michael@0 248 VMFunctionsModal(const VMFunction &info1, const VMFunction &info2) {
michael@0 249 add(info1);
michael@0 250 add(info2);
michael@0 251 }
michael@0 252
michael@0 253 inline const VMFunction &operator[](ExecutionMode mode) const {
michael@0 254 JS_ASSERT((unsigned)mode < NumExecutionModes);
michael@0 255 return funs_[mode];
michael@0 256 }
michael@0 257
michael@0 258 private:
michael@0 259 void add(const VMFunction &info) {
michael@0 260 JS_ASSERT((unsigned)info.executionMode < NumExecutionModes);
michael@0 261 funs_[info.executionMode].init(info);
michael@0 262 }
michael@0 263
michael@0 264 mozilla::Array<VMFunction, NumExecutionModes> funs_;
michael@0 265 };
michael@0 266
michael@0 267 template <class> struct TypeToDataType { /* Unexpected return type for a VMFunction. */ };
michael@0 268 template <> struct TypeToDataType<bool> { static const DataType result = Type_Bool; };
michael@0 269 template <> struct TypeToDataType<JSObject *> { static const DataType result = Type_Object; };
michael@0 270 template <> struct TypeToDataType<DeclEnvObject *> { static const DataType result = Type_Object; };
michael@0 271 template <> struct TypeToDataType<JSString *> { static const DataType result = Type_Object; };
michael@0 272 template <> struct TypeToDataType<JSFlatString *> { static const DataType result = Type_Object; };
michael@0 273 template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
michael@0 274 template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; };
michael@0 275 template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; };
michael@0 276 template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; };
michael@0 277 template <> struct TypeToDataType<Handle<StaticWithObject *> > { static const DataType result = Type_Handle; };
michael@0 278 template <> struct TypeToDataType<Handle<StaticBlockObject *> > { static const DataType result = Type_Handle; };
michael@0 279 template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; };
michael@0 280 template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; };
michael@0 281 template <> struct TypeToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
michael@0 282
michael@0 283 // Convert argument types to properties of the argument known by the jit.
michael@0 284 template <class T> struct TypeToArgProperties {
michael@0 285 static const uint32_t result =
michael@0 286 (sizeof(T) <= sizeof(void *) ? VMFunction::Word : VMFunction::Double);
michael@0 287 };
michael@0 288 template <> struct TypeToArgProperties<const Value &> {
michael@0 289 static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
michael@0 290 };
michael@0 291 template <> struct TypeToArgProperties<HandleObject> {
michael@0 292 static const uint32_t result = TypeToArgProperties<JSObject *>::result | VMFunction::ByRef;
michael@0 293 };
michael@0 294 template <> struct TypeToArgProperties<HandleString> {
michael@0 295 static const uint32_t result = TypeToArgProperties<JSString *>::result | VMFunction::ByRef;
michael@0 296 };
michael@0 297 template <> struct TypeToArgProperties<HandlePropertyName> {
michael@0 298 static const uint32_t result = TypeToArgProperties<PropertyName *>::result | VMFunction::ByRef;
michael@0 299 };
michael@0 300 template <> struct TypeToArgProperties<HandleFunction> {
michael@0 301 static const uint32_t result = TypeToArgProperties<JSFunction *>::result | VMFunction::ByRef;
michael@0 302 };
michael@0 303 template <> struct TypeToArgProperties<Handle<StaticWithObject *> > {
michael@0 304 static const uint32_t result = TypeToArgProperties<StaticWithObject *>::result | VMFunction::ByRef;
michael@0 305 };
michael@0 306 template <> struct TypeToArgProperties<Handle<StaticBlockObject *> > {
michael@0 307 static const uint32_t result = TypeToArgProperties<StaticBlockObject *>::result | VMFunction::ByRef;
michael@0 308 };
michael@0 309 template <> struct TypeToArgProperties<HandleScript> {
michael@0 310 static const uint32_t result = TypeToArgProperties<JSScript *>::result | VMFunction::ByRef;
michael@0 311 };
michael@0 312 template <> struct TypeToArgProperties<HandleValue> {
michael@0 313 static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
michael@0 314 };
michael@0 315 template <> struct TypeToArgProperties<MutableHandleValue> {
michael@0 316 static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
michael@0 317 };
michael@0 318 template <> struct TypeToArgProperties<HandleShape> {
michael@0 319 static const uint32_t result = TypeToArgProperties<Shape *>::result | VMFunction::ByRef;
michael@0 320 };
michael@0 321 template <> struct TypeToArgProperties<HandleTypeObject> {
michael@0 322 static const uint32_t result = TypeToArgProperties<types::TypeObject *>::result | VMFunction::ByRef;
michael@0 323 };
michael@0 324
michael@0 325 // Convert argument type to whether or not it should be passed in a float
michael@0 326 // register on platforms that have them, like x64.
michael@0 327 template <class T> struct TypeToPassInFloatReg {
michael@0 328 static const uint32_t result = 0;
michael@0 329 };
michael@0 330 template <> struct TypeToPassInFloatReg<double> {
michael@0 331 static const uint32_t result = 1;
michael@0 332 };
michael@0 333
michael@0 334 // Convert argument types to root types used by the gc, see MarkJitExitFrame.
michael@0 335 template <class T> struct TypeToRootType {
michael@0 336 static const uint32_t result = VMFunction::RootNone;
michael@0 337 };
michael@0 338 template <> struct TypeToRootType<HandleObject> {
michael@0 339 static const uint32_t result = VMFunction::RootObject;
michael@0 340 };
michael@0 341 template <> struct TypeToRootType<HandleString> {
michael@0 342 static const uint32_t result = VMFunction::RootString;
michael@0 343 };
michael@0 344 template <> struct TypeToRootType<HandlePropertyName> {
michael@0 345 static const uint32_t result = VMFunction::RootPropertyName;
michael@0 346 };
michael@0 347 template <> struct TypeToRootType<HandleFunction> {
michael@0 348 static const uint32_t result = VMFunction::RootFunction;
michael@0 349 };
michael@0 350 template <> struct TypeToRootType<HandleValue> {
michael@0 351 static const uint32_t result = VMFunction::RootValue;
michael@0 352 };
michael@0 353 template <> struct TypeToRootType<MutableHandleValue> {
michael@0 354 static const uint32_t result = VMFunction::RootValue;
michael@0 355 };
michael@0 356 template <> struct TypeToRootType<HandleShape> {
michael@0 357 static const uint32_t result = VMFunction::RootCell;
michael@0 358 };
michael@0 359 template <> struct TypeToRootType<HandleTypeObject> {
michael@0 360 static const uint32_t result = VMFunction::RootCell;
michael@0 361 };
michael@0 362 template <> struct TypeToRootType<HandleScript> {
michael@0 363 static const uint32_t result = VMFunction::RootCell;
michael@0 364 };
michael@0 365 template <> struct TypeToRootType<Handle<StaticBlockObject *> > {
michael@0 366 static const uint32_t result = VMFunction::RootObject;
michael@0 367 };
michael@0 368 template <> struct TypeToRootType<Handle<StaticWithObject *> > {
michael@0 369 static const uint32_t result = VMFunction::RootCell;
michael@0 370 };
michael@0 371 template <class T> struct TypeToRootType<Handle<T> > {
michael@0 372 // Fail for Handle types that aren't specialized above.
michael@0 373 };
michael@0 374
michael@0 375 template <class> struct OutParamToDataType { static const DataType result = Type_Void; };
michael@0 376 template <> struct OutParamToDataType<Value *> { static const DataType result = Type_Value; };
michael@0 377 template <> struct OutParamToDataType<int *> { static const DataType result = Type_Int32; };
michael@0 378 template <> struct OutParamToDataType<uint32_t *> { static const DataType result = Type_Int32; };
michael@0 379 template <> struct OutParamToDataType<uint8_t **> { static const DataType result = Type_Pointer; };
michael@0 380 template <> struct OutParamToDataType<bool *> { static const DataType result = Type_Bool; };
michael@0 381 template <> struct OutParamToDataType<double *> { static const DataType result = Type_Double; };
michael@0 382 template <> struct OutParamToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
michael@0 383 template <> struct OutParamToDataType<MutableHandleObject> { static const DataType result = Type_Handle; };
michael@0 384 template <> struct OutParamToDataType<MutableHandleString> { static const DataType result = Type_Handle; };
michael@0 385
michael@0 386 template <class> struct OutParamToRootType {
michael@0 387 static const VMFunction::RootType result = VMFunction::RootNone;
michael@0 388 };
michael@0 389 template <> struct OutParamToRootType<MutableHandleValue> {
michael@0 390 static const VMFunction::RootType result = VMFunction::RootValue;
michael@0 391 };
michael@0 392 template <> struct OutParamToRootType<MutableHandleObject> {
michael@0 393 static const VMFunction::RootType result = VMFunction::RootObject;
michael@0 394 };
michael@0 395 template <> struct OutParamToRootType<MutableHandleString> {
michael@0 396 static const VMFunction::RootType result = VMFunction::RootString;
michael@0 397 };
michael@0 398
michael@0 399 template <class> struct MatchContext { };
michael@0 400 template <> struct MatchContext<JSContext *> {
michael@0 401 static const ExecutionMode execMode = SequentialExecution;
michael@0 402 };
michael@0 403 template <> struct MatchContext<ExclusiveContext *> {
michael@0 404 static const ExecutionMode execMode = SequentialExecution;
michael@0 405 };
michael@0 406 template <> struct MatchContext<ForkJoinContext *> {
michael@0 407 static const ExecutionMode execMode = ParallelExecution;
michael@0 408 };
michael@0 409 template <> struct MatchContext<ThreadSafeContext *> {
michael@0 410 // ThreadSafeContext functions can be called from either mode, but for
michael@0 411 // calling from parallel they should be wrapped first, so we default to
michael@0 412 // SequentialExecution here.
michael@0 413 static const ExecutionMode execMode = SequentialExecution;
michael@0 414 };
michael@0 415
michael@0 416 #define FOR_EACH_ARGS_1(Macro, Sep, Last) Macro(1) Last(1)
michael@0 417 #define FOR_EACH_ARGS_2(Macro, Sep, Last) FOR_EACH_ARGS_1(Macro, Sep, Sep) Macro(2) Last(2)
michael@0 418 #define FOR_EACH_ARGS_3(Macro, Sep, Last) FOR_EACH_ARGS_2(Macro, Sep, Sep) Macro(3) Last(3)
michael@0 419 #define FOR_EACH_ARGS_4(Macro, Sep, Last) FOR_EACH_ARGS_3(Macro, Sep, Sep) Macro(4) Last(4)
michael@0 420 #define FOR_EACH_ARGS_5(Macro, Sep, Last) FOR_EACH_ARGS_4(Macro, Sep, Sep) Macro(5) Last(5)
michael@0 421 #define FOR_EACH_ARGS_6(Macro, Sep, Last) FOR_EACH_ARGS_5(Macro, Sep, Sep) Macro(6) Last(6)
michael@0 422
michael@0 423 #define COMPUTE_INDEX(NbArg) NbArg
michael@0 424 #define COMPUTE_OUTPARAM_RESULT(NbArg) OutParamToDataType<A ## NbArg>::result
michael@0 425 #define COMPUTE_OUTPARAM_ROOT(NbArg) OutParamToRootType<A ## NbArg>::result
michael@0 426 #define COMPUTE_ARG_PROP(NbArg) (TypeToArgProperties<A ## NbArg>::result << (2 * (NbArg - 1)))
michael@0 427 #define COMPUTE_ARG_ROOT(NbArg) (uint64_t(TypeToRootType<A ## NbArg>::result) << (3 * (NbArg - 1)))
michael@0 428 #define COMPUTE_ARG_FLOAT(NbArg) (TypeToPassInFloatReg<A ## NbArg>::result) << (NbArg - 1)
michael@0 429 #define SEP_OR(_) |
michael@0 430 #define NOTHING(_)
michael@0 431
michael@0 432 #define FUNCTION_INFO_STRUCT_BODY(ForEachNb) \
michael@0 433 static inline ExecutionMode executionMode() { \
michael@0 434 return MatchContext<Context>::execMode; \
michael@0 435 } \
michael@0 436 static inline DataType returnType() { \
michael@0 437 return TypeToDataType<R>::result; \
michael@0 438 } \
michael@0 439 static inline DataType outParam() { \
michael@0 440 return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_RESULT); \
michael@0 441 } \
michael@0 442 static inline RootType outParamRootType() { \
michael@0 443 return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_ROOT); \
michael@0 444 } \
michael@0 445 static inline size_t NbArgs() { \
michael@0 446 return ForEachNb(NOTHING, NOTHING, COMPUTE_INDEX); \
michael@0 447 } \
michael@0 448 static inline size_t explicitArgs() { \
michael@0 449 return NbArgs() - (outParam() != Type_Void ? 1 : 0); \
michael@0 450 } \
michael@0 451 static inline uint32_t argumentProperties() { \
michael@0 452 return ForEachNb(COMPUTE_ARG_PROP, SEP_OR, NOTHING); \
michael@0 453 } \
michael@0 454 static inline uint32_t argumentPassedInFloatRegs() { \
michael@0 455 return ForEachNb(COMPUTE_ARG_FLOAT, SEP_OR, NOTHING); \
michael@0 456 } \
michael@0 457 static inline uint64_t argumentRootTypes() { \
michael@0 458 return ForEachNb(COMPUTE_ARG_ROOT, SEP_OR, NOTHING); \
michael@0 459 } \
michael@0 460 FunctionInfo(pf fun, PopValues extraValuesToPop = PopValues(0)) \
michael@0 461 : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(), \
michael@0 462 argumentProperties(), argumentPassedInFloatRegs(), \
michael@0 463 argumentRootTypes(), outParam(), outParamRootType(), \
michael@0 464 returnType(), executionMode(), \
michael@0 465 extraValuesToPop.numValues) \
michael@0 466 { }
michael@0 467
michael@0 468 template <typename Fun>
michael@0 469 struct FunctionInfo {
michael@0 470 };
michael@0 471
michael@0 472 // VMFunction wrapper with no explicit arguments.
michael@0 473 template <class R, class Context>
michael@0 474 struct FunctionInfo<R (*)(Context)> : public VMFunction {
michael@0 475 typedef R (*pf)(Context);
michael@0 476
michael@0 477 static inline ExecutionMode executionMode() {
michael@0 478 return MatchContext<Context>::execMode;
michael@0 479 }
michael@0 480 static inline DataType returnType() {
michael@0 481 return TypeToDataType<R>::result;
michael@0 482 }
michael@0 483 static inline DataType outParam() {
michael@0 484 return Type_Void;
michael@0 485 }
michael@0 486 static inline RootType outParamRootType() {
michael@0 487 return RootNone;
michael@0 488 }
michael@0 489 static inline size_t explicitArgs() {
michael@0 490 return 0;
michael@0 491 }
michael@0 492 static inline uint32_t argumentProperties() {
michael@0 493 return 0;
michael@0 494 }
michael@0 495 static inline uint32_t argumentPassedInFloatRegs() {
michael@0 496 return 0;
michael@0 497 }
michael@0 498 static inline uint64_t argumentRootTypes() {
michael@0 499 return 0;
michael@0 500 }
michael@0 501 FunctionInfo(pf fun)
michael@0 502 : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(),
michael@0 503 argumentProperties(), argumentPassedInFloatRegs(),
michael@0 504 argumentRootTypes(), outParam(), outParamRootType(),
michael@0 505 returnType(), executionMode())
michael@0 506 { }
michael@0 507 };
michael@0 508
michael@0 509 // Specialize the class for each number of argument used by VMFunction.
michael@0 510 // Keep it verbose unless you find a readable macro for it.
michael@0 511 template <class R, class Context, class A1>
michael@0 512 struct FunctionInfo<R (*)(Context, A1)> : public VMFunction {
michael@0 513 typedef R (*pf)(Context, A1);
michael@0 514 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1)
michael@0 515 };
michael@0 516
michael@0 517 template <class R, class Context, class A1, class A2>
michael@0 518 struct FunctionInfo<R (*)(Context, A1, A2)> : public VMFunction {
michael@0 519 typedef R (*pf)(Context, A1, A2);
michael@0 520 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2)
michael@0 521 };
michael@0 522
michael@0 523 template <class R, class Context, class A1, class A2, class A3>
michael@0 524 struct FunctionInfo<R (*)(Context, A1, A2, A3)> : public VMFunction {
michael@0 525 typedef R (*pf)(Context, A1, A2, A3);
michael@0 526 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3)
michael@0 527 };
michael@0 528
michael@0 529 template <class R, class Context, class A1, class A2, class A3, class A4>
michael@0 530 struct FunctionInfo<R (*)(Context, A1, A2, A3, A4)> : public VMFunction {
michael@0 531 typedef R (*pf)(Context, A1, A2, A3, A4);
michael@0 532 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4)
michael@0 533 };
michael@0 534
michael@0 535 template <class R, class Context, class A1, class A2, class A3, class A4, class A5>
michael@0 536 struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5)> : public VMFunction {
michael@0 537 typedef R (*pf)(Context, A1, A2, A3, A4, A5);
michael@0 538 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5)
michael@0 539 };
michael@0 540
michael@0 541 template <class R, class Context, class A1, class A2, class A3, class A4, class A5, class A6>
michael@0 542 struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5, A6)> : public VMFunction {
michael@0 543 typedef R (*pf)(Context, A1, A2, A3, A4, A5, A6);
michael@0 544 FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_6)
michael@0 545 };
michael@0 546
michael@0 547 #undef FUNCTION_INFO_STRUCT_BODY
michael@0 548
michael@0 549 #undef FOR_EACH_ARGS_6
michael@0 550 #undef FOR_EACH_ARGS_5
michael@0 551 #undef FOR_EACH_ARGS_4
michael@0 552 #undef FOR_EACH_ARGS_3
michael@0 553 #undef FOR_EACH_ARGS_2
michael@0 554 #undef FOR_EACH_ARGS_1
michael@0 555
michael@0 556 #undef COMPUTE_INDEX
michael@0 557 #undef COMPUTE_OUTPARAM_RESULT
michael@0 558 #undef COMPUTE_OUTPARAM_ROOT
michael@0 559 #undef COMPUTE_ARG_PROP
michael@0 560 #undef COMPUTE_ARG_FLOAT
michael@0 561 #undef SEP_OR
michael@0 562 #undef NOTHING
michael@0 563
michael@0 564 class AutoDetectInvalidation
michael@0 565 {
michael@0 566 JSContext *cx_;
michael@0 567 IonScript *ionScript_;
michael@0 568 Value *rval_;
michael@0 569 bool disabled_;
michael@0 570
michael@0 571 public:
michael@0 572 AutoDetectInvalidation(JSContext *cx, Value *rval, IonScript *ionScript = nullptr);
michael@0 573
michael@0 574 void disable() {
michael@0 575 JS_ASSERT(!disabled_);
michael@0 576 disabled_ = true;
michael@0 577 }
michael@0 578
michael@0 579 ~AutoDetectInvalidation() {
michael@0 580 if (!disabled_ && ionScript_->invalidated())
michael@0 581 cx_->runtime()->setIonReturnOverride(*rval_);
michael@0 582 }
michael@0 583 };
michael@0 584
michael@0 585 bool InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Value *rval);
michael@0 586 JSObject *NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap);
michael@0 587
michael@0 588 bool CheckOverRecursed(JSContext *cx);
michael@0 589 bool CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame,
michael@0 590 uint32_t extra, uint32_t earlyCheck);
michael@0 591
michael@0 592 bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
michael@0 593 bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval);
michael@0 594 bool MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value);
michael@0 595 bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
michael@0 596
michael@0 597 template<bool Equal>
michael@0 598 bool LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
michael@0 599
michael@0 600 template<bool Equal>
michael@0 601 bool StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
michael@0 602
michael@0 603 bool LessThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
michael@0 604 bool LessThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
michael@0 605 bool GreaterThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
michael@0 606 bool GreaterThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
michael@0 607
michael@0 608 template<bool Equal>
michael@0 609 bool StringsEqual(JSContext *cx, HandleString left, HandleString right, bool *res);
michael@0 610
michael@0 611 bool IteratorMore(JSContext *cx, HandleObject obj, bool *res);
michael@0 612
michael@0 613 // Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT and parallel array inlining
michael@0 614 JSObject *NewInitParallelArray(JSContext *cx, HandleObject templateObj);
michael@0 615 JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type);
michael@0 616 JSObject *NewInitObject(JSContext *cx, HandleObject templateObject);
michael@0 617 JSObject *NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject);
michael@0 618
michael@0 619 bool ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval);
michael@0 620 bool ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length);
michael@0 621 bool ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval);
michael@0 622 JSObject *ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject res);
michael@0 623
michael@0 624 bool CharCodeAt(JSContext *cx, HandleString str, int32_t index, uint32_t *code);
michael@0 625 JSFlatString *StringFromCharCode(JSContext *cx, int32_t code);
michael@0 626
michael@0 627 bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
michael@0 628 bool strict, jsbytecode *pc);
michael@0 629
michael@0 630 bool InterruptCheck(JSContext *cx);
michael@0 631
michael@0 632 HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots);
michael@0 633 JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
michael@0 634 JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots);
michael@0 635 JSObject *NewStringObject(JSContext *cx, HandleString str);
michael@0 636
michael@0 637 bool SPSEnter(JSContext *cx, HandleScript script);
michael@0 638 bool SPSExit(JSContext *cx, HandleScript script);
michael@0 639
michael@0 640 bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, bool *out);
michael@0 641 bool OperatorInI(JSContext *cx, uint32_t index, HandleObject obj, bool *out);
michael@0 642
michael@0 643 bool GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rval);
michael@0 644
michael@0 645 bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval);
michael@0 646
michael@0 647 void GetDynamicName(JSContext *cx, JSObject *scopeChain, JSString *str, Value *vp);
michael@0 648
michael@0 649 bool FilterArgumentsOrEval(JSContext *cx, JSString *str);
michael@0 650
michael@0 651 #ifdef JSGC_GENERATIONAL
michael@0 652 void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
michael@0 653 void PostGlobalWriteBarrier(JSRuntime *rt, JSObject *obj);
michael@0 654 #endif
michael@0 655
michael@0 656 uint32_t GetIndexFromString(JSString *str);
michael@0 657
michael@0 658 bool DebugPrologue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn);
michael@0 659 bool DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok);
michael@0 660
michael@0 661 bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame);
michael@0 662 bool HeavyweightFunPrologue(JSContext *cx, BaselineFrame *frame);
michael@0 663
michael@0 664 bool NewArgumentsObject(JSContext *cx, BaselineFrame *frame, MutableHandleValue res);
michael@0 665
michael@0 666 JSObject *InitRestParameter(JSContext *cx, uint32_t length, Value *rest, HandleObject templateObj,
michael@0 667 HandleObject res);
michael@0 668
michael@0 669 bool HandleDebugTrap(JSContext *cx, BaselineFrame *frame, uint8_t *retAddr, bool *mustReturn);
michael@0 670 bool OnDebuggerStatement(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn);
michael@0 671
michael@0 672 bool EnterWith(JSContext *cx, BaselineFrame *frame, HandleValue val,
michael@0 673 Handle<StaticWithObject *> templ);
michael@0 674 bool LeaveWith(JSContext *cx, BaselineFrame *frame);
michael@0 675
michael@0 676 bool PushBlockScope(JSContext *cx, BaselineFrame *frame, Handle<StaticBlockObject *> block);
michael@0 677 bool PopBlockScope(JSContext *cx, BaselineFrame *frame);
michael@0 678 bool DebugLeaveBlock(JSContext *cx, BaselineFrame *frame, jsbytecode *pc);
michael@0 679
michael@0 680 bool InitBaselineFrameForOsr(BaselineFrame *frame, InterpreterFrame *interpFrame,
michael@0 681 uint32_t numStackValues);
michael@0 682
michael@0 683 JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject descr,
michael@0 684 HandleObject owner, int32_t offset);
michael@0 685
michael@0 686 bool ArraySpliceDense(JSContext *cx, HandleObject obj, uint32_t start, uint32_t deleteCount);
michael@0 687
michael@0 688 bool Recompile(JSContext *cx);
michael@0 689 JSString *RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp,
michael@0 690 HandleString repl);
michael@0 691 JSString *StringReplace(JSContext *cx, HandleString string, HandleString pattern,
michael@0 692 HandleString repl);
michael@0 693
michael@0 694 bool SetDenseElement(JSContext *cx, HandleObject obj, int32_t index, HandleValue value,
michael@0 695 bool strict);
michael@0 696
michael@0 697 #ifdef DEBUG
michael@0 698 void AssertValidObjectPtr(JSContext *cx, JSObject *obj);
michael@0 699 void AssertValidStringPtr(JSContext *cx, JSString *str);
michael@0 700 void AssertValidValue(JSContext *cx, Value *v);
michael@0 701 #endif
michael@0 702
michael@0 703 } // namespace jit
michael@0 704 } // namespace js
michael@0 705
michael@0 706 #endif /* jit_VMFunctions_h */

mercurial