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