#ifndef frontend_BytecodeEmitter_h
#define frontend_BytecodeEmitter_h
#include "mozilla/Attributes.h"
#include "mozilla/Span.h"
#include "ds/InlineTable.h"
#include "frontend/BCEParserHandle.h"
#include "frontend/DestructuringFlavor.h"
#include "frontend/EitherParser.h"
#include "frontend/JumpList.h"
#include "frontend/NameFunctions.h"
#include "frontend/ParseNode.h"
#include "frontend/SharedContext.h"
#include "frontend/SourceNotes.h"
#include "frontend/ValueUsage.h"
#include "vm/BytecodeUtil.h"
#include "vm/Interpreter.h"
#include "vm/Iteration.h"
namespace js {
namespace frontend {
class CGNumberList {
Rooted<ValueVector> vector;
public:
explicit CGNumberList(JSContext* cx) : vector(cx, ValueVector(cx)) {}
MOZ_MUST_USE bool append(const Value& v) { return vector.append(v); }
size_t length() const { return vector.length(); }
void finish(mozilla::Span<GCPtrValue> array);
};
struct CGObjectList {
uint32_t length;
ObjectBox* lastbox;
CGObjectList() : length(0), lastbox(nullptr) {}
unsigned add(ObjectBox* objbox);
void finish(mozilla::Span<GCPtrObject> array);
void finishInnerFunctions();
};
struct MOZ_STACK_CLASS CGScopeList {
Rooted<GCVector<Scope*>> vector;
explicit CGScopeList(JSContext* cx) : vector(cx, GCVector<Scope*>(cx)) {}
bool append(Scope* scope) { return vector.append(scope); }
uint32_t length() const { return vector.length(); }
void finish(mozilla::Span<GCPtrScope> array);
};
struct CGTryNoteList {
Vector<JSTryNote> list;
explicit CGTryNoteList(JSContext* cx) : list(cx) {}
MOZ_MUST_USE bool append(JSTryNoteKind kind, uint32_t stackDepth,
size_t start, size_t end);
size_t length() const { return list.length(); }
void finish(mozilla::Span<JSTryNote> array);
};
struct CGScopeNote : public ScopeNote {
uint32_t end;
};
struct CGScopeNoteList {
Vector<CGScopeNote> list;
explicit CGScopeNoteList(JSContext* cx) : list(cx) {}
MOZ_MUST_USE bool append(uint32_t scopeIndex, uint32_t offset,
uint32_t parent);
void recordEnd(uint32_t index, uint32_t offse);
size_t length() const { return list.length(); }
void finish(mozilla::Span<ScopeNote> array);
};
struct CGResumeOffsetList {
Vector<uint32_t> list;
explicit CGResumeOffsetList(JSContext* cx) : list(cx) {}
MOZ_MUST_USE bool append(uint32_t offset) { return list.append(offset); }
size_t length() const { return list.length(); }
void finish(mozilla::Span<uint32_t> array);
};
static constexpr size_t MaxBytecodeLength = INT32_MAX;
static constexpr size_t MaxSrcNotesLength = INT32_MAX;
typedef Vector<jsbytecode, 64> BytecodeVector;
typedef Vector<jssrcnote, 64> SrcNotesVector;
class CallOrNewEmitter;
class ElemOpEmitter;
class EmitterScope;
class NestableControl;
class PropertyEmitter;
class TDZCheckCache;
class TryEmitter;
struct MOZ_STACK_CLASS BytecodeEmitter {
SharedContext* const sc = nullptr;
JSContext* const cx = nullptr;
BytecodeEmitter* const parent = nullptr;
Rooted<JSScript*> script;
Rooted<LazyScript*> lazyScript;
private:
BytecodeVector code_;
SrcNotesVector notes_;
ptrdiff_t lastNoteOffset_ = 0;
uint32_t currentLine_ = 0;
uint32_t lastColumn_ = 0;
uint32_t lastSeparatorOffet_ = 0;
uint32_t lastSeparatorLine_ = 0;
uint32_t lastSeparatorColumn_ = 0;
mozilla::Maybe<uint32_t> mainOffset_ = {};
public:
JumpTarget lastTarget = {-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)};
mozilla::Maybe<EitherParser> ep_ = {};
BCEParserHandle* parser = nullptr;
PooledMapPtr<AtomIndexMap> atomIndices;
unsigned firstLine = 0;
uint32_t maxFixedSlots = 0;
uint32_t maxStackDepth =
0;
int32_t stackDepth = 0;
uint32_t bodyScopeIndex =
UINT32_MAX;
EmitterScope* varEmitterScope = nullptr;
NestableControl* innermostNestableControl = nullptr;
EmitterScope* innermostEmitterScope_ = nullptr;
TDZCheckCache* innermostTDZCheckCache = nullptr;
FieldInitializers fieldInitializers_;
#ifdef DEBUG
bool unstableEmitterScope = false;
friend class AutoCheckUnstableEmitterScope;
#endif
EmitterScope* innermostEmitterScope() const {
MOZ_ASSERT(!unstableEmitterScope);
return innermostEmitterScopeNoCheck();
}
EmitterScope* innermostEmitterScopeNoCheck() const {
return innermostEmitterScope_;
}
CGNumberList numberList;
CGObjectList objectList;
CGScopeList scopeList;
CGTryNoteList tryNoteList;
CGScopeNoteList scopeNoteList;
CGResumeOffsetList resumeOffsetList;
size_t numICEntries = 0;
uint32_t numYields = 0;
uint16_t typesetCount = 0;
bool hasSingletons = false;
bool hasTryFinally = false;
bool emittingRunOnceLambda = false;
bool isRunOnceLambda();
enum EmitterMode {
Normal,
SelfHosting,
LazyFunction
};
const EmitterMode emitterMode = Normal;
mozilla::Maybe<uint32_t> scriptStartOffset = {};
mozilla::Maybe<uint32_t> functionBodyEndPos = {};
private:
BytecodeEmitter(BytecodeEmitter* parent, SharedContext* sc,
HandleScript script, Handle<LazyScript*> lazyScript,
uint32_t lineNum, EmitterMode emitterMode);
void initFromBodyPosition(TokenPos bodyPosition);
void reportNeedMoreArgsError(ParseNode* pn, const char* errorName,
const char* requiredArgs, const char* pluralizer,
const ListNode* argsList);
public:
BytecodeEmitter(BytecodeEmitter* parent, BCEParserHandle* parser,
SharedContext* sc, HandleScript script,
Handle<LazyScript*> lazyScript, uint32_t lineNum,
EmitterMode emitterMode = Normal);
BytecodeEmitter(BytecodeEmitter* parent, const EitherParser& parser,
SharedContext* sc, HandleScript script,
Handle<LazyScript*> lazyScript, uint32_t lineNum,
EmitterMode emitterMode = Normal);
template <typename Unit>
BytecodeEmitter(BytecodeEmitter* parent,
Parser<FullParseHandler, Unit>* parser, SharedContext* sc,
HandleScript script, Handle<LazyScript*> lazyScript,
uint32_t lineNum, EmitterMode emitterMode = Normal)
: BytecodeEmitter(parent, EitherParser(parser), sc, script, lazyScript,
lineNum, emitterMode) {}
BytecodeEmitter(BytecodeEmitter* parent, BCEParserHandle* parser,
SharedContext* sc, HandleScript script,
Handle<LazyScript*> lazyScript, TokenPos bodyPosition,
EmitterMode emitterMode = Normal)
: BytecodeEmitter(parent, parser, sc, script, lazyScript,
parser->errorReporter().lineAt(bodyPosition.begin),
emitterMode) {
initFromBodyPosition(bodyPosition);
}
BytecodeEmitter(BytecodeEmitter* parent, const EitherParser& parser,
SharedContext* sc, HandleScript script,
Handle<LazyScript*> lazyScript, TokenPos bodyPosition,
EmitterMode emitterMode = Normal)
: BytecodeEmitter(parent, parser, sc, script, lazyScript,
parser.errorReporter().lineAt(bodyPosition.begin),
emitterMode) {
initFromBodyPosition(bodyPosition);
}
template <typename Unit>
BytecodeEmitter(BytecodeEmitter* parent,
Parser<FullParseHandler, Unit>* parser, SharedContext* sc,
HandleScript script, Handle<LazyScript*> lazyScript,
TokenPos bodyPosition, EmitterMode emitterMode = Normal)
: BytecodeEmitter(parent, EitherParser(parser), sc, script, lazyScript,
bodyPosition, emitterMode) {}
MOZ_MUST_USE bool init();
template <typename T>
T* findInnermostNestableControl() const;
template <typename T, typename Predicate >
T* findInnermostNestableControl(Predicate predicate) const;
NameLocation lookupName(JSAtom* name);
mozilla::Maybe<NameLocation> locationOfNameBoundInScope(JSAtom* name,
EmitterScope* target);
mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(
JSAtom* name, EmitterScope* source);
mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(
JSAtom* name) {
return locationOfNameBoundInFunctionScope(name, innermostEmitterScope());
}
void setVarEmitterScope(EmitterScope* emitterScope) {
MOZ_ASSERT(emitterScope);
MOZ_ASSERT(!varEmitterScope);
varEmitterScope = emitterScope;
}
Scope* outermostScope() const { return scopeList.vector[0]; }
Scope* innermostScope() const;
Scope* bodyScope() const {
MOZ_ASSERT(bodyScopeIndex < scopeList.length());
return scopeList.vector[bodyScopeIndex];
}
MOZ_ALWAYS_INLINE
MOZ_MUST_USE bool makeAtomIndex(JSAtom* atom, uint32_t* indexp) {
MOZ_ASSERT(atomIndices);
AtomIndexMap::AddPtr p = atomIndices->lookupForAdd(atom);
if (p) {
*indexp = p->value();
return true;
}
uint32_t index = atomIndices->count();
if (!atomIndices->add(p, atom, index)) {
ReportOutOfMemory(cx);
return false;
}
*indexp = index;
return true;
}
bool isInLoop();
MOZ_MUST_USE bool checkSingletonContext();
MOZ_MUST_USE bool checkRunOnceContext();
bool needsImplicitThis();
MOZ_MUST_USE bool emitThisEnvironmentCallee();
MOZ_MUST_USE bool emitSuperBase();
void tellDebuggerAboutCompiledScript(JSContext* cx);
BytecodeVector& code() { return code_; }
const BytecodeVector& code() const { return code_; }
jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
ptrdiff_t offset() const { return code_.end() - code_.begin(); }
uint32_t mainOffset() const { return *mainOffset_; }
bool inPrologue() const { return mainOffset_.isNothing(); }
void switchToMain() {
MOZ_ASSERT(inPrologue());
mainOffset_.emplace(code_.length());
}
SrcNotesVector& notes() {
MOZ_ASSERT(!inPrologue());
return notes_;
}
ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
unsigned currentLine() const { return currentLine_; }
void setCurrentLine(uint32_t line) {
currentLine_ = line;
lastColumn_ = 0;
}
bool lastOpcodeIsJumpTarget() const {
return offset() - lastTarget.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
}
ptrdiff_t lastNonJumpTargetOffset() const {
return lastOpcodeIsJumpTarget() ? lastTarget.offset : offset();
}
void setFunctionBodyEndPos(uint32_t pos) {
functionBodyEndPos = mozilla::Some(pos);
}
void setScriptStartOffsetIfUnset(uint32_t pos) {
if (scriptStartOffset.isNothing()) {
scriptStartOffset = mozilla::Some(pos);
}
}
void reportError(ParseNode* pn, unsigned errorNumber, ...);
void reportError(const mozilla::Maybe<uint32_t>& maybeOffset,
unsigned errorNumber, ...);
bool reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...);
bool reportExtraWarning(const mozilla::Maybe<uint32_t>& maybeOffset,
unsigned errorNumber, ...);
MOZ_MUST_USE bool checkSideEffects(ParseNode* pn, bool* answer);
#ifdef DEBUG
MOZ_MUST_USE bool checkStrictOrSloppy(JSOp op);
#endif
MOZ_MUST_USE bool addTryNote(JSTryNoteKind kind, uint32_t stackDepth,
size_t start, size_t end);
MOZ_MUST_USE bool newSrcNote(SrcNoteType type, unsigned* indexp = nullptr);
MOZ_MUST_USE bool newSrcNote2(SrcNoteType type, ptrdiff_t offset,
unsigned* indexp = nullptr);
MOZ_MUST_USE bool newSrcNote3(SrcNoteType type, ptrdiff_t offset1,
ptrdiff_t offset2, unsigned* indexp = nullptr);
void copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes);
MOZ_MUST_USE bool setSrcNoteOffset(unsigned index, unsigned which,
ptrdiff_t offset);
enum EmitLineNumberNote { EMIT_LINENOTE, SUPPRESS_LINENOTE };
MOZ_MUST_USE bool emitTree(ParseNode* pn,
ValueUsage valueUsage = ValueUsage::WantValue,
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
MOZ_MUST_USE bool emitScript(ParseNode* body);
enum class TopLevelFunction { No, Yes };
MOZ_MUST_USE bool emitFunctionScript(FunctionNode* funNode,
TopLevelFunction isTopLevel);
void updateDepth(ptrdiff_t target);
MOZ_MUST_USE bool markStepBreakpoint();
MOZ_MUST_USE bool markSimpleBreakpoint();
MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
void updateSeparatorPosition();
JSOp strictifySetNameOp(JSOp op);
MOZ_MUST_USE bool emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset);
MOZ_MUST_USE bool emit1(JSOp op);
MOZ_MUST_USE bool emit2(JSOp op, uint8_t op1);
MOZ_MUST_USE bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
MOZ_MUST_USE bool emitDupAt(unsigned slotFromTop);
MOZ_MUST_USE bool emitPopN(unsigned n);
MOZ_MUST_USE bool emitCheckIsObj(CheckIsObjectKind kind);
MOZ_MUST_USE bool emitCheckIsCallable(CheckIsCallableKind kind);
MOZ_MUST_USE bool emitPushNotUndefinedOrNull();
MOZ_MUST_USE bool emitUint16Operand(JSOp op, uint32_t operand);
MOZ_MUST_USE bool emitUint32Operand(JSOp op, uint32_t operand);
MOZ_MUST_USE bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
MOZ_MUST_USE bool emitNumberOp(double dval);
MOZ_MUST_USE bool emitBigIntOp(BigInt* bigint);
MOZ_MUST_USE bool emitThisLiteral(ThisLiteral* pn);
MOZ_MUST_USE bool emitGetFunctionThis(NameNode* thisName);
MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset);
MOZ_MUST_USE bool emitGetThisForSuperBase(UnaryNode* superBase);
MOZ_MUST_USE bool emitSetThis(BinaryNode* setThisNode);
MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn();
MOZ_MUST_USE bool emitJumpTargetOp(JSOp op, ptrdiff_t* off);
MOZ_MUST_USE bool emitJumpTarget(JumpTarget* target);
MOZ_MUST_USE bool emitJumpNoFallthrough(JSOp op, JumpList* jump);
MOZ_MUST_USE bool emitJump(JSOp op, JumpList* jump);
MOZ_MUST_USE bool emitBackwardJump(JSOp op, JumpTarget target, JumpList* jump,
JumpTarget* fallthrough);
void patchJumpsToTarget(JumpList jump, JumpTarget target);
MOZ_MUST_USE bool emitJumpTargetAndPatch(JumpList jump);
MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc,
const mozilla::Maybe<uint32_t>& sourceCoordOffset);
MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr);
MOZ_MUST_USE bool emitCallIncDec(UnaryNode* incDec);
mozilla::Maybe<uint32_t> getOffsetForLoop(ParseNode* nextpn);
MOZ_MUST_USE bool emitGoto(NestableControl* target, JumpList* jumplist,
SrcNoteType noteType = SRC_NULL);
MOZ_MUST_USE bool emitIndex32(JSOp op, uint32_t index);
MOZ_MUST_USE bool emitIndexOp(JSOp op, uint32_t index);
MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op);
MOZ_MUST_USE bool emitAtomOp(uint32_t atomIndex, JSOp op);
MOZ_MUST_USE bool emitArrayLiteral(ListNode* array);
MOZ_MUST_USE bool emitArray(ParseNode* arrayHead, uint32_t count);
MOZ_MUST_USE bool emitInternedScopeOp(uint32_t index, JSOp op);
MOZ_MUST_USE bool emitInternedObjectOp(uint32_t index, JSOp op);
MOZ_MUST_USE bool emitObjectOp(ObjectBox* objbox, JSOp op);
MOZ_MUST_USE bool emitObjectPairOp(ObjectBox* objbox1, ObjectBox* objbox2,
JSOp op);
MOZ_MUST_USE bool emitRegExp(uint32_t index);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(FunctionNode* funNode,
bool needsProto = false);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ListNode* objNode);
MOZ_MUST_USE bool replaceNewInitWithNewObject(JSObject* obj,
ptrdiff_t offset);
MOZ_MUST_USE bool emitHoistedFunctionsInList(ListNode* stmtList);
MOZ_MUST_USE bool emitPropertyList(ListNode* obj, PropertyEmitter& pe,
PropListType type);
FieldInitializers setupFieldInitializers(ListNode* classMembers);
MOZ_MUST_USE bool emitCreateFieldInitializers(ListNode* obj);
MOZ_MUST_USE bool emitLocalOp(JSOp op, uint32_t slot);
MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot);
MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name,
const NameLocation& loc);
MOZ_MUST_USE bool emitGetName(JSAtom* name) {
return emitGetNameAtLocation(name, lookupName(name));
}
MOZ_MUST_USE bool emitGetName(NameNode* name);
MOZ_MUST_USE bool emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc);
MOZ_MUST_USE bool emitNameIncDec(UnaryNode* incDec);
MOZ_MUST_USE bool emitDeclarationList(ListNode* declList);
MOZ_MUST_USE bool emitSingleDeclaration(ListNode* declList, NameNode* decl,
ParseNode* initializer);
MOZ_MUST_USE bool emitNewInit();
MOZ_MUST_USE bool emitSingletonInitialiser(ListNode* objOrArray);
MOZ_MUST_USE bool emitPrepareIteratorResult();
MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() {
return emitGetDotGeneratorInScope(*innermostEmitterScope());
}
MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope);
MOZ_MUST_USE bool allocateResumeIndex(ptrdiff_t offset,
uint32_t* resumeIndex);
MOZ_MUST_USE bool allocateResumeIndexRange(mozilla::Span<ptrdiff_t> offsets,
uint32_t* firstResumeIndex);
MOZ_MUST_USE bool emitInitialYield(UnaryNode* yieldNode);
MOZ_MUST_USE bool emitYield(UnaryNode* yieldNode);
MOZ_MUST_USE bool emitYieldOp(JSOp op);
MOZ_MUST_USE bool emitYieldStar(ParseNode* iter);
MOZ_MUST_USE bool emitAwaitInInnermostScope() {
return emitAwaitInScope(*innermostEmitterScope());
}
MOZ_MUST_USE bool emitAwaitInInnermostScope(UnaryNode* awaitNode);
MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope);
MOZ_MUST_USE bool emitPropLHS(PropertyAccess* prop);
MOZ_MUST_USE bool emitPropIncDec(UnaryNode* incDec);
MOZ_MUST_USE bool emitComputedPropertyName(UnaryNode* computedPropName);
enum class EmitElemOption { Get, Call, IncDec, CompoundAssign, Ref };
MOZ_MUST_USE bool emitElemOperands(PropertyByValue* elem,
EmitElemOption opts);
MOZ_MUST_USE bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper,
ElemOpEmitter& eoe);
MOZ_MUST_USE bool emitElemOpBase(JSOp op);
MOZ_MUST_USE bool emitElemOp(PropertyByValue* elem, JSOp op);
MOZ_MUST_USE bool emitElemIncDec(UnaryNode* incDec);
MOZ_MUST_USE bool emitCatch(BinaryNode* catchClause);
MOZ_MUST_USE bool emitIf(TernaryNode* ifNode);
MOZ_MUST_USE bool emitWith(BinaryNode* withNode);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(
const LabeledStatement* labeledStmt);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(
LexicalScopeNode* lexicalScope);
MOZ_MUST_USE bool emitLexicalScopeBody(
ParseNode* body, EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TryNode* tryNode);
MOZ_MUST_USE bool emitGoSub(JumpList* jump);
MOZ_MUST_USE bool emitDestructuringLHSRef(ParseNode* target, size_t* emitted);
MOZ_MUST_USE bool emitSetOrInitializeDestructuring(ParseNode* target,
DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ListNode* pattern);
MOZ_MUST_USE bool emitDestructuringOps(ListNode* pattern,
DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOpsArray(ListNode* pattern,
DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOpsObject(ListNode* pattern,
DestructuringFlavor flav);
enum class CopyOption { Filtered, Unfiltered };
MOZ_MUST_USE bool emitCopyDataProperties(CopyOption option);
MOZ_MUST_USE bool emitIterator();
MOZ_MUST_USE bool emitAsyncIterator();
MOZ_MUST_USE bool emitIteratorNext(
const mozilla::Maybe<uint32_t>& callSourceCoordOffset,
IteratorKind kind = IteratorKind::Sync, bool allowSelfHosted = false);
MOZ_MUST_USE bool emitIteratorCloseInScope(
EmitterScope& currentScope, IteratorKind iterKind = IteratorKind::Sync,
CompletionKind completionKind = CompletionKind::Normal,
bool allowSelfHosted = false);
MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(
IteratorKind iterKind = IteratorKind::Sync,
CompletionKind completionKind = CompletionKind::Normal,
bool allowSelfHosted = false) {
return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind,
completionKind, allowSelfHosted);
}
template <typename InnerEmitter>
MOZ_MUST_USE bool wrapWithDestructuringTryNote(int32_t iterDepth,
InnerEmitter emitter);
MOZ_MUST_USE bool defineHoistedTopLevelFunctions(ParseNode* body);
MOZ_MUST_USE bool emitDefault(ParseNode* defaultExpr, ParseNode* pattern);
MOZ_MUST_USE bool emitAnonymousFunctionWithName(ParseNode* node,
HandleAtom name);
MOZ_MUST_USE bool emitAnonymousFunctionWithComputedName(
ParseNode* node, FunctionPrefixKind prefixKind);
MOZ_MUST_USE bool setFunName(JSFunction* fun, JSAtom* name);
MOZ_MUST_USE bool emitInitializer(ParseNode* initializer, ParseNode* pattern);
MOZ_MUST_USE bool emitCallSiteObject(CallSiteNode* callSiteObj);
MOZ_MUST_USE bool emitTemplateString(ListNode* templateString);
MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp compoundOp,
ParseNode* rhs);
MOZ_MUST_USE bool emitReturn(UnaryNode* returnNode);
MOZ_MUST_USE bool emitExpressionStatement(UnaryNode* exprStmt);
MOZ_MUST_USE bool emitStatementList(ListNode* stmtList);
MOZ_MUST_USE bool emitDeleteName(UnaryNode* deleteNode);
MOZ_MUST_USE bool emitDeleteProperty(UnaryNode* deleteNode);
MOZ_MUST_USE bool emitDeleteElement(UnaryNode* deleteNode);
MOZ_MUST_USE bool emitDeleteExpression(UnaryNode* deleteNode);
MOZ_MUST_USE bool emitTypeof(UnaryNode* typeofNode, JSOp op);
MOZ_MUST_USE bool emitUnary(UnaryNode* unaryNode);
MOZ_MUST_USE bool emitRightAssociative(ListNode* node);
MOZ_MUST_USE bool emitLeftAssociative(ListNode* node);
MOZ_MUST_USE bool emitLogical(ListNode* node);
MOZ_MUST_USE bool emitSequenceExpr(
ListNode* node, ValueUsage valueUsage = ValueUsage::WantValue);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(UnaryNode* incDec);
MOZ_MUST_USE bool emitConditionalExpression(
ConditionalExpression& conditional,
ValueUsage valueUsage = ValueUsage::WantValue);
bool isRestParameter(ParseNode* expr);
MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall,
bool isSpread, CallOrNewEmitter& cone);
MOZ_MUST_USE bool emitCallOrNew(
BinaryNode* callNode, ValueUsage valueUsage = ValueUsage::WantValue);
MOZ_MUST_USE bool emitSelfHostedCallFunction(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedResumeGenerator(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedForceInterpreter();
MOZ_MUST_USE bool emitSelfHostedAllowContentIter(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedDefineDataProperty(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedGetPropertySuper(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedHasOwn(BinaryNode* callNode);
MOZ_MUST_USE bool emitDo(BinaryNode* doNode);
MOZ_MUST_USE bool emitWhile(BinaryNode* whileNode);
MOZ_MUST_USE bool emitFor(
ForNode* forNode, const EmitterScope* headLexicalEmitterScope = nullptr);
MOZ_MUST_USE bool emitCStyleFor(ForNode* forNode,
const EmitterScope* headLexicalEmitterScope);
MOZ_MUST_USE bool emitForIn(ForNode* forNode,
const EmitterScope* headLexicalEmitterScope);
MOZ_MUST_USE bool emitForOf(ForNode* forNode,
const EmitterScope* headLexicalEmitterScope);
MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead);
MOZ_MUST_USE bool emitBreak(PropertyName* label);
MOZ_MUST_USE bool emitContinue(PropertyName* label);
MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
MOZ_MUST_USE bool emitLexicalInitialization(NameNode* name);
MOZ_MUST_USE bool emitLexicalInitialization(JSAtom* name);
MOZ_MUST_USE bool emitSpread(bool allowSelfHosted = false);
enum class ClassNameKind {
BindingName,
InferredName,
ComputedName
};
MOZ_MUST_USE bool emitClass(
ClassNode* classNode, ClassNameKind nameKind = ClassNameKind::BindingName,
HandleAtom nameForAnonymousClass = nullptr);
MOZ_MUST_USE bool emitSuperElemOperands(
PropertyByValue* elem, EmitElemOption opts = EmitElemOption::Get);
MOZ_MUST_USE bool emitSuperGetElem(PropertyByValue* elem,
bool isCall = false);
MOZ_MUST_USE bool emitCalleeAndThis(ParseNode* callee, ParseNode* call,
CallOrNewEmitter& cone);
MOZ_MUST_USE bool emitPipeline(ListNode* node);
MOZ_MUST_USE bool emitExportDefault(BinaryNode* exportNode);
};
class MOZ_RAII AutoCheckUnstableEmitterScope {
#ifdef DEBUG
bool prev_;
BytecodeEmitter* bce_;
#endif
public:
AutoCheckUnstableEmitterScope() = delete;
explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce)
#ifdef DEBUG
: bce_(bce)
#endif
{
#ifdef DEBUG
prev_ = bce_->unstableEmitterScope;
bce_->unstableEmitterScope = true;
#endif
}
~AutoCheckUnstableEmitterScope() {
#ifdef DEBUG
bce_->unstableEmitterScope = prev_;
#endif
}
};
}
}
#endif