VMFunctions.h (29424B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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/Assertions.h" 11 #include "mozilla/HashFunctions.h" 12 13 #include <stddef.h> 14 #include <stdint.h> 15 16 #include "jstypes.h" 17 #include "NamespaceImports.h" 18 19 #include "gc/AllocKind.h" 20 #include "js/ScalarType.h" 21 #include "js/TypeDecls.h" 22 #include "vm/TypeofEqOperand.h" 23 #include "vm/UsingHint.h" 24 25 class JSJitInfo; 26 class JSLinearString; 27 28 namespace js { 29 30 class AbstractGeneratorObject; 31 class ArrayObject; 32 class DateObject; 33 class FixedLengthTypedArrayObject; 34 class GlobalObject; 35 class InterpreterFrame; 36 class LexicalScope; 37 class ClassBodyScope; 38 class MapObject; 39 class NativeObject; 40 class PlainObject; 41 class PropertyName; 42 class SetObject; 43 class Shape; 44 class TypedArrayObject; 45 class WithScope; 46 class MegamorphicCacheEntry; 47 48 namespace gc { 49 50 struct Cell; 51 52 } // namespace gc 53 54 namespace wasm { 55 56 class AnyRef; 57 58 } // namespace wasm 59 60 namespace jit { 61 62 class BaselineFrame; 63 class InterpreterStubExitFrameLayout; 64 65 enum DataType : uint8_t { 66 Type_Void, 67 Type_Bool, 68 Type_Int32, 69 Type_Double, 70 Type_Pointer, 71 Type_Cell, 72 Type_Value, 73 Type_Handle 74 }; 75 76 // [SMDOC] JIT-to-C++ Function Calls. (callVM) 77 // 78 // Sometimes it is easier to reuse C++ code by calling VM's functions. Calling a 79 // function from the VM can be achieved with the use of callWithABI but this is 80 // discouraged when the called functions might trigger exceptions and/or 81 // garbage collections which are expecting to walk the stack. VMFunctions and 82 // callVM are interfaces provided to handle the exception handling and register 83 // the stack end (JITActivation) such that walking the stack is made possible. 84 // 85 // VMFunctionData is a structure which contains the necessary information needed 86 // for generating a trampoline function to make a call (with generateVMWrapper) 87 // and to root the arguments of the function (in TraceJitExitFrame). 88 // VMFunctionData is created with the VMFunctionDataHelper template, which 89 // infers the VMFunctionData fields from the function signature. The rooting and 90 // trampoline code is therefore determined by the arguments of a function and 91 // their locations in the signature of a function. 92 // 93 // VM functions all expect a JSContext* as first argument. This argument is 94 // implicitly provided by the trampoline code (in generateVMWrapper) and used 95 // for creating new objects or reporting errors. If your function does not make 96 // use of a JSContext* argument, then you might probably use a callWithABI 97 // call. 98 // 99 // Functions described using the VMFunction system must conform to a simple 100 // protocol: the return type must have a special "failure" value (for example, 101 // false for bool, or nullptr for Objects). If the function is designed to 102 // return a value that does not meet this requirement - such as 103 // object-or-nullptr, or an integer, an optional, final outParam can be 104 // specified. In this case, the return type must be boolean to indicate 105 // failure. 106 // 107 // JIT Code usage: 108 // 109 // Different JIT compilers in SpiderMonkey have their own implementations of 110 // callVM to call VM functions. However, the general shape of them is that 111 // arguments (excluding the JSContext or trailing out-param) are pushed on to 112 // the stack from right to left (rightmost argument is pushed first). 113 // 114 // Regardless of return value protocol being used (final outParam, or return 115 // value) the generated trampolines ensure the return value ends up in 116 // JSReturnOperand, ReturnReg or ReturnDoubleReg. 117 // 118 // Example: 119 // 120 // The details will differ slightly between the different compilers in 121 // SpiderMonkey, but the general shape of our usage looks like this: 122 // 123 // Suppose we have a function Foo: 124 // 125 // bool Foo(JSContext* cx, HandleObject x, HandleId y, 126 // MutableHandleValue z); 127 // 128 // This function returns true on success, and z is the outparam return value. 129 // 130 // A VM function wrapper for this can be created by adding an entry to 131 // VM_FUNCTION_LIST in VMFunctionList-inl.h: 132 // 133 // _(Foo, js::Foo) 134 // 135 // In the compiler code the call would then be issued like this: 136 // 137 // masm.Push(id); 138 // masm.Push(obj); 139 // 140 // using Fn = bool (*)(JSContext*, HandleObject, HandleId, 141 // MutableHandleValue); 142 // if (!callVM<Fn, js::Foo>()) { 143 // return false; 144 // } 145 // 146 // After this, the result value is in the return value register. 147 148 // Data for a VM function. All VMFunctionDatas are stored in a constexpr array. 149 struct VMFunctionData { 150 #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_ION_PERF) 151 // Informative name of the wrapped function. The name should not be present 152 // in release builds in order to save memory. 153 const char* name_; 154 #endif 155 156 // Note: a maximum of seven root types is supported. 157 enum RootType : uint8_t { 158 RootNone = 0, 159 RootObject, 160 RootString, 161 RootId, 162 RootValue, 163 RootCell, 164 RootBigInt 165 }; 166 167 // Contains an combination of enumerated types used by the gc for marking 168 // arguments of the VM wrapper. 169 uint64_t argumentRootTypes; 170 171 enum ArgProperties { 172 WordByValue = 0, 173 DoubleByValue = 1, 174 WordByRef = 2, 175 DoubleByRef = 3, 176 // BitMask version. 177 Word = 0, 178 Double = 1, 179 ByRef = 2 180 }; 181 182 // Contains properties about the first 16 arguments. 183 uint32_t argumentProperties; 184 185 // Which arguments should be passed in float register on platforms that 186 // have them. 187 uint32_t argumentPassedInFloatRegs; 188 189 // Number of arguments expected, excluding JSContext * as an implicit 190 // first argument and an outparam as a possible implicit final argument. 191 uint8_t explicitArgs; 192 193 // The root type of the out param if outParam == Type_Handle. 194 RootType outParamRootType; 195 196 // The outparam may be any Type_*, and must be the final argument to the 197 // function, if not Void. outParam != Void implies that the return type 198 // has a boolean failure mode. 199 DataType outParam; 200 201 // Type returned by the C function and used by the VMFunction wrapper to 202 // check for failures of the C function. Valid failure/return types are 203 // boolean and object pointers which are asserted inside the VMFunction 204 // constructor. If the C function use an outparam (!= Type_Void), then 205 // the only valid failure/return type is boolean -- object pointers are 206 // pointless because the wrapper will only use it to compare it against 207 // nullptr before discarding its value. 208 DataType returnType; 209 210 // Number of Values the VM wrapper should pop from the stack when it returns. 211 // Used by baseline IC stubs so that they can use tail calls to call the VM 212 // wrapper. 213 uint8_t extraValuesToPop; 214 215 uint32_t argc() const { 216 // JSContext * + args + (OutParam? *) 217 return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1); 218 } 219 220 DataType failType() const { return returnType; } 221 222 // Whether this function returns anything more than a boolean flag for 223 // failures. 224 bool returnsData() const { 225 return returnType == Type_Cell || outParam != Type_Void; 226 } 227 228 ArgProperties argProperties(uint32_t explicitArg) const { 229 return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3); 230 } 231 232 RootType argRootType(uint32_t explicitArg) const { 233 return RootType((argumentRootTypes >> (3 * explicitArg)) & 7); 234 } 235 236 bool argPassedInFloatReg(uint32_t explicitArg) const { 237 return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1; 238 } 239 240 #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_ION_PERF) 241 const char* name() const { return name_; } 242 #endif 243 244 // Return the stack size consumed by explicit arguments. 245 size_t explicitStackSlots() const { 246 size_t stackSlots = explicitArgs; 247 248 // Fetch all double-word flags of explicit arguments. 249 uint32_t n = ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. 250 & 0x55555555 // = Mask double-size args. 251 & argumentProperties; 252 253 // Add the number of double-word flags. (expect a few loop 254 // iteration) 255 while (n) { 256 stackSlots++; 257 n &= n - 1; 258 } 259 return stackSlots; 260 } 261 262 // Double-size argument which are passed by value are taking the space 263 // of 2 C arguments. This function is used to compute the number of 264 // argument expected by the C function. This is not the same as 265 // explicitStackSlots because reference to stack slots may take one less 266 // register in the total count. 267 size_t explicitArgc() const { 268 size_t stackSlots = explicitArgs; 269 270 // Fetch all explicit arguments. 271 uint32_t n = ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. 272 & argumentProperties; 273 274 // Filter double-size arguments (0x5 = 0b0101) and remove (& ~) 275 // arguments passed by reference (0b1010 >> 1 == 0b0101). 276 n = (n & 0x55555555) & ~(n >> 1); 277 278 // Add the number of double-word transfered by value. (expect a few 279 // loop iteration) 280 while (n) { 281 stackSlots++; 282 n &= n - 1; 283 } 284 return stackSlots; 285 } 286 287 size_t doubleByRefArgs() const { 288 size_t count = 0; 289 290 // Fetch all explicit arguments. 291 uint32_t n = ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. 292 & argumentProperties; 293 294 // Filter double-size arguments (0x5 = 0b0101) and take (&) only 295 // arguments passed by reference (0b1010 >> 1 == 0b0101). 296 n = (n & 0x55555555) & (n >> 1); 297 298 // Add the number of double-word transfered by refference. (expect a 299 // few loop iterations) 300 while (n) { 301 count++; 302 n &= n - 1; 303 } 304 return count; 305 } 306 307 size_t sizeOfOutParamStackSlot() const; 308 309 constexpr VMFunctionData(const char* name, uint32_t explicitArgs, 310 uint32_t argumentProperties, 311 uint32_t argumentPassedInFloatRegs, 312 uint64_t argRootTypes, DataType outParam, 313 RootType outParamRootType, DataType returnType, 314 uint8_t extraValuesToPop = 0) 315 : 316 #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_ION_PERF) 317 name_(name), 318 #endif 319 argumentRootTypes(argRootTypes), 320 argumentProperties(argumentProperties), 321 argumentPassedInFloatRegs(argumentPassedInFloatRegs), 322 explicitArgs(explicitArgs), 323 outParamRootType(outParamRootType), 324 outParam(outParam), 325 returnType(returnType), 326 extraValuesToPop(extraValuesToPop) { 327 // Check for valid failure/return type. 328 MOZ_ASSERT_IF(outParam != Type_Void, 329 returnType == Type_Void || returnType == Type_Bool); 330 MOZ_ASSERT(returnType == Type_Void || returnType == Type_Bool || 331 returnType == Type_Cell); 332 } 333 334 constexpr VMFunctionData(const VMFunctionData& o) = default; 335 }; 336 337 // Extract the last element of a list of types. 338 template <typename... ArgTypes> 339 struct LastArg; 340 341 template <> 342 struct LastArg<> { 343 using Type = void; 344 }; 345 346 template <typename HeadType> 347 struct LastArg<HeadType> { 348 using Type = HeadType; 349 }; 350 351 template <typename HeadType, typename... TailTypes> 352 struct LastArg<HeadType, TailTypes...> { 353 using Type = typename LastArg<TailTypes...>::Type; 354 }; 355 356 [[nodiscard]] bool InvokeFunction(JSContext* cx, HandleObject obj0, 357 bool constructing, bool ignoresReturnValue, 358 uint32_t argc, Value* argv, 359 MutableHandleValue rval); 360 361 bool InvokeFromInterpreterStub(JSContext* cx, 362 InterpreterStubExitFrameLayout* frame); 363 void* GetContextSensitiveInterpreterStub(); 364 365 bool CheckOverRecursed(JSContext* cx); 366 bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame); 367 368 [[nodiscard]] bool MutatePrototype(JSContext* cx, Handle<PlainObject*> obj, 369 HandleValue value); 370 371 enum class EqualityKind : bool { NotEqual, Equal }; 372 373 template <EqualityKind Kind> 374 bool StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res); 375 376 enum class ComparisonKind : bool { GreaterThanOrEqual, LessThan }; 377 378 template <ComparisonKind Kind> 379 bool StringsCompare(JSContext* cx, HandleString lhs, HandleString rhs, 380 bool* res); 381 382 JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep); 383 [[nodiscard]] bool SetArrayLength(JSContext* cx, HandleObject obj, 384 HandleValue value, bool strict); 385 386 [[nodiscard]] bool CharCodeAt(JSContext* cx, HandleString str, int32_t index, 387 uint32_t* code); 388 [[nodiscard]] bool CodePointAt(JSContext* cx, HandleString str, int32_t index, 389 uint32_t* code); 390 JSLinearString* StringFromCharCodeNoGC(JSContext* cx, int32_t code); 391 JSLinearString* LinearizeForCharAccessPure(JSString* str); 392 JSLinearString* LinearizeForCharAccess(JSContext* cx, JSString* str); 393 int32_t StringTrimStartIndex(const JSString* str); 394 int32_t StringTrimEndIndex(const JSString* str, int32_t start); 395 JSString* CharCodeToLowerCase(JSContext* cx, int32_t code); 396 JSString* CharCodeToUpperCase(JSContext* cx, int32_t code); 397 398 [[nodiscard]] bool SetProperty(JSContext* cx, HandleObject obj, 399 Handle<PropertyName*> name, HandleValue value, 400 bool strict, jsbytecode* pc); 401 402 [[nodiscard]] bool InterruptCheck(JSContext* cx); 403 404 JSObject* NewStringObject(JSContext* cx, HandleString str); 405 406 bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out); 407 408 [[nodiscard]] bool GetIntrinsicValue(JSContext* cx, Handle<PropertyName*> name, 409 MutableHandleValue rval); 410 411 [[nodiscard]] bool CreateThisFromIC(JSContext* cx, HandleObject callee, 412 HandleObject newTarget, 413 MutableHandleValue rval); 414 [[nodiscard]] bool CreateThisFromIon(JSContext* cx, HandleObject callee, 415 HandleObject newTarget, 416 MutableHandleValue rval); 417 418 void PostWriteBarrier(JSRuntime* rt, js::gc::Cell* cell); 419 void PostGlobalWriteBarrier(JSRuntime* rt, GlobalObject* obj); 420 421 void PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index); 422 423 // If |str| represents an int32, assign it to |result| and return true. 424 // Otherwise return false. 425 bool GetInt32FromStringPure(JSContext* cx, JSString* str, int32_t* result); 426 427 // If |str| is an index in the range [0, INT32_MAX], return it. If the string 428 // is not an index in this range, return -1. 429 int32_t GetIndexFromString(JSString* str); 430 431 JSObject* WrapObjectPure(JSContext* cx, JSObject* obj); 432 433 [[nodiscard]] bool DebugPrologue(JSContext* cx, BaselineFrame* frame); 434 [[nodiscard]] bool DebugEpilogue(JSContext* cx, BaselineFrame* frame, 435 const jsbytecode* pc, bool ok); 436 [[nodiscard]] bool DebugEpilogueOnBaselineReturn(JSContext* cx, 437 BaselineFrame* frame, 438 const jsbytecode* pc); 439 void FrameIsDebuggeeCheck(BaselineFrame* frame); 440 441 JSObject* CreateGeneratorFromFrame(JSContext* cx, BaselineFrame* frame); 442 JSObject* CreateGenerator(JSContext* cx, HandleFunction, HandleScript, 443 HandleObject, HandleObject); 444 445 [[nodiscard]] bool NormalSuspend(JSContext* cx, HandleObject obj, 446 BaselineFrame* frame, uint32_t frameSize, 447 const jsbytecode* pc); 448 [[nodiscard]] bool FinalSuspend(JSContext* cx, HandleObject obj, 449 const jsbytecode* pc); 450 [[nodiscard]] bool InterpretResume(JSContext* cx, HandleObject obj, 451 Value* stackValues, MutableHandleValue rval); 452 [[nodiscard]] bool DebugAfterYield(JSContext* cx, BaselineFrame* frame); 453 [[nodiscard]] bool GeneratorThrowOrReturn( 454 JSContext* cx, BaselineFrame* frame, 455 Handle<AbstractGeneratorObject*> genObj, HandleValue arg, 456 int32_t resumeKindArg); 457 458 [[nodiscard]] bool GlobalDeclInstantiationFromIon(JSContext* cx, 459 HandleScript script, 460 const jsbytecode* pc); 461 [[nodiscard]] bool InitFunctionEnvironmentObjects(JSContext* cx, 462 BaselineFrame* frame); 463 464 [[nodiscard]] bool NewArgumentsObject(JSContext* cx, BaselineFrame* frame, 465 MutableHandleValue res); 466 467 ArrayObject* NewArrayObjectEnsureDenseInitLength(JSContext* cx, int32_t count); 468 469 ArrayObject* InitRestParameter(JSContext* cx, uint32_t length, Value* rest, 470 Handle<ArrayObject*> arrRes); 471 472 [[nodiscard]] bool HandleDebugTrap(JSContext* cx, BaselineFrame* frame, 473 const uint8_t* retAddr); 474 [[nodiscard]] bool OnDebuggerStatement(JSContext* cx, BaselineFrame* frame); 475 [[nodiscard]] bool GlobalHasLiveOnDebuggerStatement(JSContext* cx); 476 477 [[nodiscard]] bool EnterWith(JSContext* cx, BaselineFrame* frame, 478 HandleValue val, Handle<WithScope*> templ); 479 [[nodiscard]] bool LeaveWith(JSContext* cx, BaselineFrame* frame); 480 481 [[nodiscard]] bool PushLexicalEnv(JSContext* cx, BaselineFrame* frame, 482 Handle<LexicalScope*> scope); 483 [[nodiscard]] bool PushClassBodyEnv(JSContext* cx, BaselineFrame* frame, 484 Handle<ClassBodyScope*> scope); 485 [[nodiscard]] bool DebugLeaveThenPopLexicalEnv(JSContext* cx, 486 BaselineFrame* frame, 487 const jsbytecode* pc); 488 [[nodiscard]] bool FreshenLexicalEnv(JSContext* cx, BaselineFrame* frame); 489 [[nodiscard]] bool DebuggeeFreshenLexicalEnv(JSContext* cx, 490 BaselineFrame* frame, 491 const jsbytecode* pc); 492 [[nodiscard]] bool RecreateLexicalEnv(JSContext* cx, BaselineFrame* frame); 493 [[nodiscard]] bool DebuggeeRecreateLexicalEnv(JSContext* cx, 494 BaselineFrame* frame, 495 const jsbytecode* pc); 496 [[nodiscard]] bool DebugLeaveLexicalEnv(JSContext* cx, BaselineFrame* frame, 497 const jsbytecode* pc); 498 499 [[nodiscard]] bool PushVarEnv(JSContext* cx, BaselineFrame* frame, 500 Handle<Scope*> scope); 501 502 [[nodiscard]] bool InitBaselineFrameForOsr(BaselineFrame* frame, 503 InterpreterFrame* interpFrame, 504 uint32_t numStackValues); 505 506 JSString* StringReplace(JSContext* cx, HandleString string, 507 HandleString pattern, HandleString repl); 508 509 void AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi); 510 void AssertValidObjectPtr(JSContext* cx, JSObject* obj); 511 void AssertValidStringPtr(JSContext* cx, JSString* str); 512 void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym); 513 void AssertValidValue(JSContext* cx, Value* v); 514 515 void JitValuePreWriteBarrier(JSRuntime* rt, Value* vp); 516 void JitStringPreWriteBarrier(JSRuntime* rt, JSString** stringp); 517 void JitObjectPreWriteBarrier(JSRuntime* rt, JSObject** objp); 518 void JitShapePreWriteBarrier(JSRuntime* rt, Shape** shapep); 519 void JitWasmAnyRefPreWriteBarrier(JSRuntime* rt, wasm::AnyRef* refp); 520 521 bool ObjectIsCallable(JSObject* obj); 522 bool ObjectIsConstructor(JSObject* obj); 523 JSObject* ObjectKeys(JSContext* cx, HandleObject obj); 524 JSObject* ObjectKeysFromIterator(JSContext* cx, HandleObject iterObj); 525 bool ObjectKeysLength(JSContext* cx, HandleObject obj, int32_t* length); 526 527 [[nodiscard]] bool ThrowRuntimeLexicalError(JSContext* cx, 528 unsigned errorNumber); 529 530 [[nodiscard]] bool ThrowBadDerivedReturnOrUninitializedThis(JSContext* cx, 531 HandleValue v); 532 533 [[nodiscard]] bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, 534 MutableHandleValue res); 535 536 [[nodiscard]] bool CallNativeGetter(JSContext* cx, HandleFunction callee, 537 HandleValue receiver, 538 MutableHandleValue result); 539 540 bool CallDOMGetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj, 541 MutableHandleValue result); 542 543 bool CallDOMSetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj, 544 HandleValue value); 545 546 [[nodiscard]] bool CallNativeSetter(JSContext* cx, HandleFunction callee, 547 HandleObject obj, HandleValue rhs); 548 549 [[nodiscard]] bool EqualStringsHelperPure(JSString* str1, JSString* str2); 550 551 void HandleCodeCoverageAtPC(BaselineFrame* frame, jsbytecode* pc); 552 void HandleCodeCoverageAtPrologue(BaselineFrame* frame); 553 554 bool CheckProxyGetByValueResult(JSContext* cx, HandleObject obj, HandleValue id, 555 HandleValue value, MutableHandleValue result); 556 557 bool GetNativeDataPropertyPure(JSContext* cx, JSObject* obj, PropertyKey id, 558 MegamorphicCacheEntry* entry, Value* vp); 559 560 bool GetNativeDataPropertyPureWithCacheLookup(JSContext* cx, JSObject* obj, 561 PropertyKey id, 562 MegamorphicCacheEntry* entry, 563 Value* vp); 564 565 bool GetNativeDataPropertyByValuePure(JSContext* cx, JSObject* obj, 566 MegamorphicCacheEntry* cacheEntry, 567 Value* vp); 568 569 bool GetPropMaybeCached(JSContext* cx, HandleObject obj, HandleId id, 570 MegamorphicCacheEntry* cacheEntry, 571 MutableHandleValue result); 572 573 bool GetElemMaybeCached(JSContext* cx, HandleObject obj, HandleValue id, 574 MegamorphicCacheEntry* cacheEntry, 575 MutableHandleValue result); 576 577 template <bool HasOwn> 578 bool HasNativeDataPropertyPure(JSContext* cx, JSObject* obj, 579 MegamorphicCacheEntry* cacheEntry, Value* vp); 580 581 bool HasNativeElementPure(JSContext* cx, NativeObject* obj, int32_t index, 582 Value* vp); 583 584 bool ObjectHasGetterSetterPure(JSContext* cx, JSObject* objArg, jsid id, 585 GetterSetter* getterSetter); 586 587 template <bool Cached> 588 bool SetElementMegamorphic(JSContext* cx, HandleObject obj, HandleValue index, 589 HandleValue value, bool strict); 590 591 template <bool Cached> 592 bool SetPropertyMegamorphic(JSContext* cx, HandleObject obj, HandleId id, 593 HandleValue value, bool strict); 594 595 JSString* TypeOfNameObject(JSObject* obj, JSRuntime* rt); 596 597 bool TypeOfEqObject(JSObject* obj, TypeofEqOperand operand); 598 599 bool GetPrototypeOf(JSContext* cx, HandleObject target, 600 MutableHandleValue rval); 601 602 bool DoConcatStringObject(JSContext* cx, HandleValue lhs, HandleValue rhs, 603 MutableHandleValue res); 604 605 bool IsPossiblyWrappedTypedArray(JSContext* cx, JSObject* obj, bool* result); 606 607 void* AllocateDependentString(JSContext* cx); 608 void* AllocateFatInlineString(JSContext* cx); 609 void* AllocateBigIntNoGC(JSContext* cx, bool requestMinorGC); 610 void AllocateAndInitTypedArrayBuffer(JSContext* cx, 611 FixedLengthTypedArrayObject* obj, 612 int32_t count, size_t inlineCapacity); 613 614 #ifdef JS_GC_PROBES 615 void TraceCreateObject(JSObject* obj); 616 #endif 617 618 bool PreserveWrapper(JSContext* cx, JSObject* obj); 619 620 bool DoStringToInt64(JSContext* cx, HandleString str, uint64_t* res); 621 622 BigInt* CreateBigIntFromInt32(JSContext* cx, int32_t i32); 623 624 #if JS_BITS_PER_WORD == 32 625 BigInt* CreateBigIntFromInt64(JSContext* cx, uint32_t low, uint32_t high); 626 BigInt* CreateBigIntFromUint64(JSContext* cx, uint32_t low, uint32_t high); 627 #else 628 BigInt* CreateBigIntFromInt64(JSContext* cx, uint64_t i64); 629 BigInt* CreateBigIntFromUint64(JSContext* cx, uint64_t i64); 630 #endif 631 632 template <EqualityKind Kind> 633 bool BigIntEqual(BigInt* x, BigInt* y); 634 635 template <ComparisonKind Kind> 636 bool BigIntCompare(BigInt* x, BigInt* y); 637 638 template <EqualityKind Kind> 639 bool BigIntNumberEqual(BigInt* x, double y); 640 641 template <ComparisonKind Kind> 642 bool BigIntNumberCompare(BigInt* x, double y); 643 644 template <ComparisonKind Kind> 645 bool NumberBigIntCompare(double x, BigInt* y); 646 647 template <EqualityKind Kind> 648 bool BigIntStringEqual(JSContext* cx, HandleBigInt x, HandleString y, 649 bool* res); 650 651 template <ComparisonKind Kind> 652 bool BigIntStringCompare(JSContext* cx, HandleBigInt x, HandleString y, 653 bool* res); 654 655 template <ComparisonKind Kind> 656 bool StringBigIntCompare(JSContext* cx, HandleString x, HandleBigInt y, 657 bool* res); 658 659 BigInt* BigIntAsIntN(JSContext* cx, HandleBigInt x, int32_t bits); 660 BigInt* BigIntAsUintN(JSContext* cx, HandleBigInt x, int32_t bits); 661 662 using AtomicsCompareExchangeFn = int32_t (*)(TypedArrayObject*, size_t, int32_t, 663 int32_t); 664 665 using AtomicsReadWriteModifyFn = int32_t (*)(TypedArrayObject*, size_t, 666 int32_t); 667 668 AtomicsCompareExchangeFn AtomicsCompareExchange(Scalar::Type elementType); 669 AtomicsReadWriteModifyFn AtomicsExchange(Scalar::Type elementType); 670 AtomicsReadWriteModifyFn AtomicsAdd(Scalar::Type elementType); 671 AtomicsReadWriteModifyFn AtomicsSub(Scalar::Type elementType); 672 AtomicsReadWriteModifyFn AtomicsAnd(Scalar::Type elementType); 673 AtomicsReadWriteModifyFn AtomicsOr(Scalar::Type elementType); 674 AtomicsReadWriteModifyFn AtomicsXor(Scalar::Type elementType); 675 676 BigInt* AtomicsLoad64(JSContext* cx, TypedArrayObject* typedArray, 677 size_t index); 678 679 void AtomicsStore64(TypedArrayObject* typedArray, size_t index, 680 const BigInt* value); 681 682 BigInt* AtomicsCompareExchange64(JSContext* cx, TypedArrayObject* typedArray, 683 size_t index, const BigInt* expected, 684 const BigInt* replacement); 685 686 BigInt* AtomicsExchange64(JSContext* cx, TypedArrayObject* typedArray, 687 size_t index, const BigInt* value); 688 689 BigInt* AtomicsAdd64(JSContext* cx, TypedArrayObject* typedArray, size_t index, 690 const BigInt* value); 691 BigInt* AtomicsAnd64(JSContext* cx, TypedArrayObject* typedArray, size_t index, 692 const BigInt* value); 693 BigInt* AtomicsOr64(JSContext* cx, TypedArrayObject* typedArray, size_t index, 694 const BigInt* value); 695 BigInt* AtomicsSub64(JSContext* cx, TypedArrayObject* typedArray, size_t index, 696 const BigInt* value); 697 BigInt* AtomicsXor64(JSContext* cx, TypedArrayObject* typedArray, size_t index, 698 const BigInt* value); 699 700 float RoundFloat16ToFloat32(int32_t d); 701 float RoundFloat16ToFloat32(float d); 702 float RoundFloat16ToFloat32(double d); 703 704 float Float16ToFloat32(int32_t value); 705 int32_t Float32ToFloat16(float value); 706 707 void DateFillLocalTimeSlots(DateObject* dateObj); 708 709 JSAtom* AtomizeStringNoGC(JSContext* cx, JSString* str); 710 711 bool SetObjectHas(JSContext* cx, Handle<SetObject*> obj, HandleValue key, 712 bool* rval); 713 bool SetObjectDelete(JSContext* cx, Handle<SetObject*> obj, HandleValue key, 714 bool* rval); 715 bool SetObjectAdd(JSContext* cx, Handle<SetObject*> obj, HandleValue key); 716 bool SetObjectAddFromIC(JSContext* cx, Handle<SetObject*> obj, HandleValue key, 717 MutableHandleValue rval); 718 bool MapObjectHas(JSContext* cx, Handle<MapObject*> obj, HandleValue key, 719 bool* rval); 720 bool MapObjectGet(JSContext* cx, Handle<MapObject*> obj, HandleValue key, 721 MutableHandleValue rval); 722 bool MapObjectDelete(JSContext* cx, Handle<MapObject*> obj, HandleValue key, 723 bool* rval); 724 bool MapObjectSet(JSContext* cx, Handle<MapObject*> obj, HandleValue key, 725 HandleValue val); 726 bool MapObjectSetFromIC(JSContext* cx, Handle<MapObject*> obj, HandleValue key, 727 HandleValue val, MutableHandleValue rval); 728 729 void AssertSetObjectHash(JSContext* cx, SetObject* obj, const Value* value, 730 mozilla::HashNumber actualHash); 731 void AssertMapObjectHash(JSContext* cx, MapObject* obj, const Value* value, 732 mozilla::HashNumber actualHash); 733 734 void AssertPropertyLookup(NativeObject* obj, PropertyKey id, uint32_t slot); 735 736 void ReadBarrier(gc::Cell* cell); 737 738 // Functions used when JS_MASM_VERBOSE is enabled. 739 void AssumeUnreachable(const char* output); 740 void Printf0(const char* output); 741 void Printf1(const char* output, uintptr_t value); 742 743 enum class VMFunctionId; 744 745 extern const VMFunctionData& GetVMFunction(VMFunctionId id); 746 747 extern size_t NumVMFunctions(); 748 749 } // namespace jit 750 } // namespace js 751 752 #if defined(JS_CODEGEN_ARM) 753 extern "C" { 754 extern MOZ_EXPORT int64_t __aeabi_idivmod(int, int); 755 extern MOZ_EXPORT int64_t __aeabi_uidivmod(int, int); 756 } 757 #endif 758 759 #endif /* jit_VMFunctions_h */