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