Interpreter.h (28330B)
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 vm_Interpreter_h 8 #define vm_Interpreter_h 9 10 /* 11 * JS interpreter interface. 12 */ 13 14 #include "jspubtd.h" 15 16 #include "vm/BuiltinObjectKind.h" 17 #include "vm/CheckIsObjectKind.h" // CheckIsObjectKind 18 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 19 # include "vm/ErrorObject.h" 20 # include "vm/UsingHint.h" 21 #endif 22 #include "vm/Stack.h" 23 24 namespace js { 25 26 class WithScope; 27 class EnvironmentIter; 28 class PlainObject; 29 30 /* 31 * Convert null/undefined |thisv| into the global lexical's |this| object, and 32 * replace other primitives with boxed versions. 33 */ 34 extern JSObject* BoxNonStrictThis(JSContext* cx, HandleValue thisv); 35 36 extern bool GetFunctionThis(JSContext* cx, AbstractFramePtr frame, 37 MutableHandleValue res); 38 39 extern void GetNonSyntacticGlobalThis(JSContext* cx, HandleObject envChain, 40 MutableHandleValue res); 41 42 /* 43 * numToSkip is the number of stack values the expression decompiler should skip 44 * before it reaches |v|. If it's -1, the decompiler will search the stack. 45 */ 46 extern bool ReportIsNotFunction(JSContext* cx, HandleValue v, int numToSkip, 47 MaybeConstruct construct = NO_CONSTRUCT); 48 49 /* See ReportIsNotFunction comment for the meaning of numToSkip. */ 50 extern JSObject* ValueToCallable(JSContext* cx, HandleValue v, 51 int numToSkip = -1, 52 MaybeConstruct construct = NO_CONSTRUCT); 53 54 // Reasons why a call could be performed, for passing onto the debugger's 55 // `onNativeCall` hook. 56 // `onNativeCall` hook disabled all JITs, and this needs to be handled only in 57 // the interpreter. 58 enum class CallReason { 59 Call, 60 // callContentFunction or constructContentFunction in self-hosted JS. 61 CallContent, 62 // Function.prototype.call or Function.prototype.apply. 63 FunCall, 64 Getter, 65 Setter, 66 }; 67 68 /* 69 * Call or construct arguments that are stored in rooted memory. 70 * 71 * NOTE: Any necessary |GetThisValue| computation must have been performed on 72 * |args.thisv()|, likely by the interpreter when pushing |this| onto the 73 * stack. If you're not sure whether |GetThisValue| processing has been 74 * performed, use |Invoke|. 75 */ 76 extern bool InternalCallOrConstruct(JSContext* cx, const CallArgs& args, 77 MaybeConstruct construct, 78 CallReason reason = CallReason::Call); 79 80 /* 81 * These helpers take care of the infinite-recursion check necessary for 82 * getter/setter calls. 83 */ 84 extern bool CallGetter(JSContext* cx, HandleValue thisv, HandleValue getter, 85 MutableHandleValue rval); 86 87 extern bool CallSetter(JSContext* cx, HandleValue thisv, HandleValue setter, 88 HandleValue rval); 89 90 // ES7 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 91 // 7.3.12 Call(F, V, argumentsList). 92 // All parameters are required, hopefully forcing callers to be careful not to 93 // (say) blindly pass callee as |newTarget| when a different value should have 94 // been passed. Behavior is unspecified if any element of |args| isn't 95 // initialized. 96 // 97 // |rval| is written to *only* after |fval| and |thisv| have been consumed, so 98 // |rval| *may* alias either argument. 99 extern bool Call(JSContext* cx, HandleValue fval, HandleValue thisv, 100 const AnyInvokeArgs& args, MutableHandleValue rval, 101 CallReason reason = CallReason::Call); 102 103 inline bool Call(JSContext* cx, HandleValue fval, HandleValue thisv, 104 MutableHandleValue rval) { 105 FixedInvokeArgs<0> args(cx); 106 return Call(cx, fval, thisv, args, rval); 107 } 108 109 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj, 110 MutableHandleValue rval) { 111 RootedValue thisv(cx, ObjectOrNullValue(thisObj)); 112 FixedInvokeArgs<0> args(cx); 113 return Call(cx, fval, thisv, args, rval); 114 } 115 116 inline bool Call(JSContext* cx, HandleValue fval, HandleValue thisv, 117 HandleValue arg0, MutableHandleValue rval) { 118 FixedInvokeArgs<1> args(cx); 119 args[0].set(arg0); 120 return Call(cx, fval, thisv, args, rval); 121 } 122 123 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj, 124 HandleValue arg0, MutableHandleValue rval) { 125 RootedValue thisv(cx, ObjectOrNullValue(thisObj)); 126 FixedInvokeArgs<1> args(cx); 127 args[0].set(arg0); 128 return Call(cx, fval, thisv, args, rval); 129 } 130 131 inline bool Call(JSContext* cx, HandleValue fval, HandleValue thisv, 132 HandleValue arg0, HandleValue arg1, MutableHandleValue rval) { 133 FixedInvokeArgs<2> args(cx); 134 args[0].set(arg0); 135 args[1].set(arg1); 136 return Call(cx, fval, thisv, args, rval); 137 } 138 139 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj, 140 HandleValue arg0, HandleValue arg1, MutableHandleValue rval) { 141 RootedValue thisv(cx, ObjectOrNullValue(thisObj)); 142 FixedInvokeArgs<2> args(cx); 143 args[0].set(arg0); 144 args[1].set(arg1); 145 return Call(cx, fval, thisv, args, rval); 146 } 147 148 inline bool Call(JSContext* cx, HandleValue fval, JSObject* thisObj, 149 HandleValue arg0, HandleValue arg1, HandleValue arg2, 150 MutableHandleValue rval) { 151 RootedValue thisv(cx, ObjectOrNullValue(thisObj)); 152 FixedInvokeArgs<3> args(cx); 153 args[0].set(arg0); 154 args[1].set(arg1); 155 args[2].set(arg2); 156 return Call(cx, fval, thisv, args, rval); 157 } 158 159 // Perform the above Call() operation using the given arguments. Similar to 160 // ConstructFromStack() below, this handles |!IsCallable(args.calleev())|. 161 // 162 // This internal operation is intended only for use with arguments known to be 163 // on the JS stack, or at least in carefully-rooted memory. The vast majority of 164 // potential users should instead use InvokeArgs in concert with Call(). 165 extern bool CallFromStack(JSContext* cx, const CallArgs& args, 166 CallReason reason = CallReason::Call); 167 168 // ES6 7.3.13 Construct(F, argumentsList, newTarget). All parameters are 169 // required, hopefully forcing callers to be careful not to (say) blindly pass 170 // callee as |newTarget| when a different value should have been passed. 171 // Behavior is unspecified if any element of |args| isn't initialized. 172 // 173 // |rval| is written to *only* after |fval| and |newTarget| have been consumed, 174 // so |rval| *may* alias either argument. 175 // 176 // NOTE: As with the ES6 spec operation, it's the caller's responsibility to 177 // ensure |fval| and |newTarget| are both |IsConstructor|. 178 extern bool Construct(JSContext* cx, HandleValue fval, 179 const AnyConstructArgs& args, HandleValue newTarget, 180 MutableHandleObject objp); 181 182 // Check that in the given |args|, which must be |args.isConstructing()|, that 183 // |IsConstructor(args.callee())|. If this is not the case, throw a TypeError. 184 // Otherwise, the user must ensure that, additionally, 185 // |IsConstructor(args.newTarget())|. (If |args| comes directly from the 186 // interpreter stack, as set up by JSOp::New, this comes for free.) Then perform 187 // a Construct() operation using |args|. 188 // 189 // This internal operation is intended only for use with arguments known to be 190 // on the JS stack, or at least in carefully-rooted memory. The vast majority of 191 // potential users should instead use ConstructArgs in concert with Construct(). 192 extern bool ConstructFromStack(JSContext* cx, const CallArgs& args, 193 CallReason reason = CallReason::Call); 194 195 // Call Construct(fval, args, newTarget), but use the given |thisv| as |this| 196 // during construction of |fval|. 197 // 198 // |rval| is written to *only* after |fval|, |thisv|, and |newTarget| have been 199 // consumed, so |rval| *may* alias any of these arguments. 200 // 201 // This method exists only for very rare cases where a |this| was created 202 // caller-side for construction of |fval|: basically only for JITs using 203 // |CreateThis|. If that's not you, use Construct()! 204 extern bool InternalConstructWithProvidedThis(JSContext* cx, HandleValue fval, 205 HandleValue thisv, 206 const AnyConstructArgs& args, 207 HandleValue newTarget, 208 MutableHandleValue rval); 209 210 /* 211 * Executes a script with the given envChain. To support debugging, the 212 * evalInFrame parameter can point to an arbitrary frame in the context's call 213 * stack to simulate executing an eval in that frame. 214 */ 215 extern bool ExecuteKernel(JSContext* cx, HandleScript script, 216 HandleObject envChainArg, 217 AbstractFramePtr evalInFrame, 218 MutableHandleValue result); 219 220 /* Execute a script with the given envChain as global code. */ 221 extern bool Execute(JSContext* cx, HandleScript script, HandleObject envChain, 222 MutableHandleValue rval); 223 224 class ExecuteState; 225 class InvokeState; 226 227 // RunState is passed to RunScript and RunScript then either passes it to the 228 // interpreter or to the JITs. RunState contains all information we need to 229 // construct an interpreter or JIT frame. 230 class MOZ_RAII RunState { 231 protected: 232 enum Kind { Execute, Invoke }; 233 Kind kind_; 234 235 RootedScript script_; 236 237 explicit RunState(JSContext* cx, Kind kind, JSScript* script) 238 : kind_(kind), script_(cx, script) {} 239 240 public: 241 bool isExecute() const { return kind_ == Execute; } 242 bool isInvoke() const { return kind_ == Invoke; } 243 244 ExecuteState* asExecute() const { 245 MOZ_ASSERT(isExecute()); 246 return (ExecuteState*)this; 247 } 248 InvokeState* asInvoke() const { 249 MOZ_ASSERT(isInvoke()); 250 return (InvokeState*)this; 251 } 252 253 JS::HandleScript script() const { return script_; } 254 255 InterpreterFrame* pushInterpreterFrame(JSContext* cx); 256 inline void setReturnValue(const Value& v); 257 258 private: 259 RunState(const RunState& other) = delete; 260 RunState(const ExecuteState& other) = delete; 261 RunState(const InvokeState& other) = delete; 262 void operator=(const RunState& other) = delete; 263 }; 264 265 // Eval or global script. 266 class MOZ_RAII ExecuteState : public RunState { 267 HandleObject envChain_; 268 269 AbstractFramePtr evalInFrame_; 270 MutableHandleValue result_; 271 272 public: 273 ExecuteState(JSContext* cx, JSScript* script, HandleObject envChain, 274 AbstractFramePtr evalInFrame, MutableHandleValue result) 275 : RunState(cx, Execute, script), 276 envChain_(envChain), 277 evalInFrame_(evalInFrame), 278 result_(result) {} 279 280 JSObject* environmentChain() const { return envChain_; } 281 bool isDebuggerEval() const { return !!evalInFrame_; } 282 283 InterpreterFrame* pushInterpreterFrame(JSContext* cx); 284 285 void setReturnValue(const Value& v) { result_.set(v); } 286 }; 287 288 // Data to invoke a function. 289 class MOZ_RAII InvokeState final : public RunState { 290 const CallArgs& args_; 291 MaybeConstruct construct_; 292 293 public: 294 InvokeState(JSContext* cx, const CallArgs& args, MaybeConstruct construct) 295 : RunState(cx, Invoke, args.callee().as<JSFunction>().nonLazyScript()), 296 args_(args), 297 construct_(construct) {} 298 299 bool constructing() const { return construct_; } 300 const CallArgs& args() const { return args_; } 301 302 InterpreterFrame* pushInterpreterFrame(JSContext* cx); 303 304 void setReturnValue(const Value& v) { args_.rval().set(v); } 305 }; 306 307 inline void RunState::setReturnValue(const Value& v) { 308 if (isInvoke()) { 309 asInvoke()->setReturnValue(v); 310 } else { 311 asExecute()->setReturnValue(v); 312 } 313 } 314 315 extern bool RunScript(JSContext* cx, RunState& state); 316 extern bool Interpret(JSContext* cx, RunState& state); 317 318 extern JSType TypeOfObject(JSObject* obj); 319 320 extern JSType TypeOfValue(const Value& v); 321 322 // Implementation of 323 // https://www.ecma-international.org/ecma-262/6.0/#sec-instanceofoperator 324 extern bool InstanceofOperator(JSContext* cx, HandleObject obj, HandleValue v, 325 bool* bp); 326 327 // Unwind environment chain and iterator to match the scope corresponding to 328 // the given bytecode position. 329 extern void UnwindEnvironment(JSContext* cx, EnvironmentIter& ei, 330 jsbytecode* pc); 331 332 // Unwind all environments. 333 extern void UnwindAllEnvironmentsInFrame(JSContext* cx, EnvironmentIter& ei); 334 335 // Compute the pc needed to unwind the scope to the beginning of the block 336 // pointed to by the try note. 337 extern jsbytecode* UnwindEnvironmentToTryPc(JSScript* script, 338 const TryNote* tn); 339 340 namespace detail { 341 342 template <class TryNoteFilter> 343 class MOZ_STACK_CLASS BaseTryNoteIter { 344 uint32_t pcOffset_; 345 TryNoteFilter isTryNoteValid_; 346 347 const TryNote* tn_; 348 const TryNote* tnEnd_; 349 350 void settle() { 351 for (; tn_ != tnEnd_; ++tn_) { 352 if (!pcInRange()) { 353 continue; 354 } 355 356 /* Try notes cannot be disjoint. That is, we can't have 357 * multiple notes with disjoint pc ranges jumping to the same 358 * catch block. This interacts awkwardly with for-of loops, in 359 * which calls to IteratorClose emitted due to abnormal 360 * completion (break, throw, return) are emitted inline, at the 361 * source location of the break, throw, or return 362 * statement. For example: 363 * 364 * for (x of iter) { 365 * try { return; } catch (e) { } 366 * } 367 * 368 * From the try-note nesting's perspective, the IteratorClose 369 * resulting from |return| is covered by the inner try, when it 370 * should not be. If IteratorClose throws, we don't want to 371 * catch it here. 372 * 373 * To make this work, we use TryNoteKind::ForOfIterClose try-notes, 374 * which cover the range of the abnormal completion. When 375 * looking up trynotes, a for-of iterclose note indicates that 376 * the enclosing for-of has just been terminated. As a result, 377 * trynotes within that for-of are no longer active. When we 378 * see a for-of-iterclose, we skip ahead in the trynotes list 379 * until we see the matching for-of. 380 * 381 * Breaking out of multiple levels of for-of at once is handled 382 * using nested TryNoteKind::ForOfIterClose try-notes. Consider this 383 * code: 384 * 385 * try { 386 * loop: for (i of first) { 387 * <A> 388 * for (j of second) { 389 * <B> 390 * break loop; // <C1/2> 391 * } 392 * } 393 * } catch {...} 394 * 395 * Here is the mapping from various PCs to try-notes that we 396 * want to return: 397 * 398 * A B C1 C2 399 * | | | | 400 * | | | [---|---] ForOfIterClose (outer) 401 * | | [---|------|---] ForOfIterClose (inner) 402 * | [--X-----|------|----] ForOf (inner) 403 * [---X-----------X------|-----] ForOf (outer) 404 * [------------------------X------] TryCatch 405 * 406 * - At A, we find the outer for-of. 407 * - At B, we find the inner for-of. 408 * - At C1, we find one TryNoteKind::ForOfIterClose, skip past one 409 * TryNoteKind::ForOf, and find the outer for-of. (This occurs if an 410 * exception is thrown while closing the inner iterator.) 411 * - At C2, we find two TryNoteKind::ForOfIterClose, skip past two 412 * TryNoteKind::ForOf, and reach the outer try-catch. (This occurs if 413 * an exception is thrown while closing the outer iterator.) 414 */ 415 if (tn_->kind() == TryNoteKind::ForOfIterClose) { 416 uint32_t iterCloseDepth = 1; 417 do { 418 ++tn_; 419 MOZ_ASSERT(tn_ != tnEnd_); 420 if (pcInRange()) { 421 if (tn_->kind() == TryNoteKind::ForOfIterClose) { 422 iterCloseDepth++; 423 } else if (tn_->kind() == TryNoteKind::ForOf) { 424 iterCloseDepth--; 425 } 426 } 427 } while (iterCloseDepth > 0); 428 429 // Advance to trynote following the enclosing for-of. 430 continue; 431 } 432 433 /* 434 * We have a note that covers the exception pc but we must check 435 * whether the interpreter has already executed the corresponding 436 * handler. This is possible when the executed bytecode implements 437 * break or return from inside a for-in loop. 438 * 439 * In this case the emitter generates additional [enditer] and [goto] 440 * opcodes to close all outstanding iterators and execute the finally 441 * blocks. If such an [enditer] throws an exception, its pc can still 442 * be inside several nested for-in loops and try-finally statements 443 * even if we have already closed the corresponding iterators and 444 * invoked the finally blocks. 445 * 446 * To address this, we make [enditer] always decrease the stack even 447 * when its implementation throws an exception. Thus already executed 448 * [enditer] and [goto] opcodes will have try notes with the stack 449 * depth exceeding the current one and this condition is what we use to 450 * filter them out. 451 */ 452 if (tn_ == tnEnd_ || isTryNoteValid_(tn_)) { 453 return; 454 } 455 } 456 } 457 458 public: 459 BaseTryNoteIter(JSScript* script, jsbytecode* pc, 460 TryNoteFilter isTryNoteValid) 461 : pcOffset_(script->pcToOffset(pc)), isTryNoteValid_(isTryNoteValid) { 462 // NOTE: The Span is a temporary so we can't use begin()/end() 463 // here or the iterator will outlive the span. 464 auto trynotes = script->trynotes(); 465 tn_ = trynotes.data(); 466 tnEnd_ = tn_ + trynotes.size(); 467 468 settle(); 469 } 470 471 void operator++() { 472 ++tn_; 473 settle(); 474 } 475 476 bool pcInRange() const { 477 // This checks both ends of the range at once 478 // because unsigned integers wrap on underflow. 479 uint32_t offset = pcOffset_; 480 uint32_t start = tn_->start; 481 uint32_t length = tn_->length; 482 return offset - start < length; 483 } 484 bool done() const { return tn_ == tnEnd_; } 485 const TryNote* operator*() const { return tn_; } 486 }; 487 488 } // namespace detail 489 490 template <class TryNoteFilter> 491 class MOZ_STACK_CLASS TryNoteIter 492 : public detail::BaseTryNoteIter<TryNoteFilter> { 493 using Base = detail::BaseTryNoteIter<TryNoteFilter>; 494 495 // Keep the script alive as long as the iterator is live. 496 RootedScript script_; 497 498 public: 499 TryNoteIter(JSContext* cx, JSScript* script, jsbytecode* pc, 500 TryNoteFilter isTryNoteValid) 501 : Base(script, pc, isTryNoteValid), script_(cx, script) {} 502 }; 503 504 class NoOpTryNoteFilter { 505 public: 506 explicit NoOpTryNoteFilter() = default; 507 bool operator()(const TryNote*) { return true; } 508 }; 509 510 // Iterator over all try notes. Code using this iterator is not allowed to 511 // trigger GC to make sure the script stays alive. See TryNoteIter above for the 512 // can-GC version. 513 class MOZ_STACK_CLASS TryNoteIterAllNoGC 514 : public detail::BaseTryNoteIter<NoOpTryNoteFilter> { 515 using Base = detail::BaseTryNoteIter<NoOpTryNoteFilter>; 516 JS::AutoCheckCannotGC nogc; 517 518 public: 519 TryNoteIterAllNoGC(JSScript* script, jsbytecode* pc) 520 : Base(script, pc, NoOpTryNoteFilter()) {} 521 }; 522 523 bool HandleClosingGeneratorReturn(JSContext* cx, AbstractFramePtr frame, 524 bool ok); 525 526 /************************************************************************/ 527 528 bool ThrowOperation(JSContext* cx, HandleValue v); 529 530 bool ThrowWithStackOperation(JSContext* cx, HandleValue v, HandleValue stack); 531 532 bool GetPendingExceptionStack(JSContext* cx, MutableHandleValue vp); 533 534 bool GetProperty(JSContext* cx, HandleValue value, Handle<PropertyName*> name, 535 MutableHandleValue vp); 536 537 JSObject* LambdaBaselineFallback(JSContext* cx, HandleFunction fun, 538 HandleObject parent, gc::AllocSite* site); 539 JSObject* LambdaOptimizedFallback(JSContext* cx, HandleFunction fun, 540 HandleObject parent, gc::Heap heap); 541 JSObject* Lambda(JSContext* cx, HandleFunction fun, HandleObject parent, 542 gc::Heap heap = gc::Heap::Default, 543 gc::AllocSite* site = nullptr); 544 545 bool SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, 546 HandleValue value, bool strict); 547 548 bool SetObjectElementWithReceiver(JSContext* cx, HandleObject obj, 549 HandleValue index, HandleValue value, 550 HandleValue receiver, bool strict); 551 552 bool AddValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 553 MutableHandleValue res); 554 555 bool SubValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 556 MutableHandleValue res); 557 558 bool MulValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 559 MutableHandleValue res); 560 561 bool DivValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 562 MutableHandleValue res); 563 564 bool ModValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 565 MutableHandleValue res); 566 567 bool PowValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 568 MutableHandleValue res); 569 570 bool BitNot(JSContext* cx, MutableHandleValue in, MutableHandleValue res); 571 572 bool BitXor(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 573 MutableHandleValue res); 574 575 bool BitOr(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 576 MutableHandleValue res); 577 578 bool BitAnd(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 579 MutableHandleValue res); 580 581 bool BitLsh(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 582 MutableHandleValue res); 583 584 bool BitRsh(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 585 MutableHandleValue res); 586 587 bool UrshValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 588 MutableHandleValue res); 589 590 bool LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 591 bool* res); 592 593 bool LessThanOrEqual(JSContext* cx, MutableHandleValue lhs, 594 MutableHandleValue rhs, bool* res); 595 596 bool GreaterThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, 597 bool* res); 598 599 bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs, 600 MutableHandleValue rhs, bool* res); 601 602 template <bool strict> 603 bool DelPropOperation(JSContext* cx, HandleValue val, 604 Handle<PropertyName*> name, bool* res); 605 606 template <bool strict> 607 bool DelElemOperation(JSContext* cx, HandleValue val, HandleValue index, 608 bool* res); 609 610 JSObject* BindVarOperation(JSContext* cx, JSObject* envChain); 611 612 JSObject* ImportMetaOperation(JSContext* cx, HandleScript script); 613 614 JSObject* BuiltinObjectOperation(JSContext* cx, BuiltinObjectKind kind); 615 616 bool ThrowMsgOperation(JSContext* cx, const unsigned throwMsgKind); 617 618 bool GetAndClearException(JSContext* cx, MutableHandleValue res); 619 620 bool GetAndClearExceptionAndStack(JSContext* cx, MutableHandleValue res, 621 MutableHandle<SavedFrame*> stack); 622 623 bool DeleteNameOperation(JSContext* cx, Handle<PropertyName*> name, 624 HandleObject envChain, MutableHandleValue res); 625 626 void ImplicitThisOperation(JSContext* cx, HandleObject env, 627 MutableHandleValue res); 628 629 bool InitPropGetterSetterOperation(JSContext* cx, jsbytecode* pc, 630 HandleObject obj, Handle<PropertyName*> name, 631 HandleObject val); 632 633 unsigned GetInitDataPropAttrs(JSOp op); 634 635 bool EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val, 636 Handle<WithScope*> scope); 637 638 bool InitElemGetterSetterOperation(JSContext* cx, jsbytecode* pc, 639 HandleObject obj, HandleValue idval, 640 HandleObject val); 641 642 bool SpreadCallOperation(JSContext* cx, HandleScript script, jsbytecode* pc, 643 HandleValue thisv, HandleValue callee, HandleValue arr, 644 HandleValue newTarget, MutableHandleValue res); 645 646 bool OptimizeSpreadCall(JSContext* cx, HandleValue arg, 647 MutableHandleValue result); 648 649 bool OptimizeGetIterator(Value arg, JSContext* cx); 650 651 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 652 enum class SyncDisposalClosureSlots : uint8_t { 653 Method, 654 }; 655 bool SyncDisposalClosure(JSContext* cx, unsigned argc, JS::Value* vp); 656 657 ErrorObject* CreateSuppressedError(JSContext* cx, JS::Handle<JS::Value> error, 658 JS::Handle<JS::Value> suppressed); 659 660 bool AddDisposableResourceToCapability(JSContext* cx, JS::Handle<JSObject*> env, 661 JS::Handle<JS::Value> val, 662 JS::Handle<JS::Value> method, 663 bool needsClosure, UsingHint hint); 664 #endif 665 666 ArrayObject* ArrayFromArgumentsObject(JSContext* cx, 667 Handle<ArgumentsObject*> args); 668 669 JSObject* NewObjectOperation(JSContext* cx, HandleScript script, 670 const jsbytecode* pc); 671 672 JSObject* NewPlainObjectBaselineFallback(JSContext* cx, 673 Handle<SharedShape*> shape, 674 gc::AllocKind allocKind, 675 gc::AllocSite* site); 676 677 JSObject* NewPlainObjectOptimizedFallback(JSContext* cx, 678 Handle<SharedShape*> shape, 679 gc::AllocKind allocKind, 680 gc::Heap initialHeap); 681 682 ArrayObject* NewArrayOperation(JSContext* cx, uint32_t length, 683 NewObjectKind newKind = GenericObject); 684 685 // Called from JIT code when inline array allocation fails. 686 ArrayObject* NewArrayObjectBaselineFallback(JSContext* cx, uint32_t length, 687 gc::AllocKind allocKind, 688 gc::AllocSite* site); 689 ArrayObject* NewArrayObjectOptimizedFallback(JSContext* cx, uint32_t length, 690 gc::AllocKind allocKind, 691 NewObjectKind newKind); 692 693 [[nodiscard]] bool GetImportOperation(JSContext* cx, HandleObject envChain, 694 HandleScript script, jsbytecode* pc, 695 MutableHandleValue vp); 696 697 void ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, 698 HandleId id); 699 700 void ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, 701 Handle<PropertyName*> name); 702 703 void ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, 704 HandleScript script, jsbytecode* pc); 705 706 void ReportInNotObjectError(JSContext* cx, HandleValue lref, HandleValue rref); 707 708 bool ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind); 709 710 bool ThrowUninitializedThis(JSContext* cx); 711 712 bool ThrowInitializedThis(JSContext* cx); 713 714 bool ThrowObjectCoercible(JSContext* cx, HandleValue value); 715 716 bool Debug_CheckSelfHosted(JSContext* cx, HandleValue funVal); 717 718 bool CheckClassHeritageOperation(JSContext* cx, HandleValue heritage); 719 720 PlainObject* ObjectWithProtoOperation(JSContext* cx, HandleValue proto); 721 722 JSObject* FunWithProtoOperation(JSContext* cx, HandleFunction fun, 723 HandleObject parent, HandleObject proto); 724 725 bool SetPropertySuper(JSContext* cx, HandleValue lval, HandleValue receiver, 726 Handle<PropertyName*> name, HandleValue rval, 727 bool strict); 728 729 bool SetElementSuper(JSContext* cx, HandleValue lval, HandleValue receiver, 730 HandleValue index, HandleValue rval, bool strict); 731 732 bool LoadAliasedDebugVar(JSContext* cx, JSObject* env, jsbytecode* pc, 733 MutableHandleValue result); 734 735 bool CloseIterOperation(JSContext* cx, HandleObject iter, CompletionKind kind); 736 } /* namespace js */ 737 738 #endif /* vm_Interpreter_h */