diff options
Diffstat (limited to 'js/src/frontend/AsyncEmitter.h')
-rw-r--r-- | js/src/frontend/AsyncEmitter.h | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/js/src/frontend/AsyncEmitter.h b/js/src/frontend/AsyncEmitter.h new file mode 100644 index 0000000000..7ed945351c --- /dev/null +++ b/js/src/frontend/AsyncEmitter.h @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef frontend_AsyncEmitter_h +#define frontend_AsyncEmitter_h + +#include "mozilla/Attributes.h" // MOZ_STACK_CLASS, MOZ_MUST_USE + +#include "frontend/TryEmitter.h" // TryEmitter + +namespace js { +namespace frontend { + +struct BytecodeEmitter; + +// Class for emitting Bytecode associated with the AsyncFunctionGenerator. +// +// Usage: +// +// For an async function, the params have to be handled separately, +// because the body may have pushed an additional var environment, changing +// the number of hops required to reach the |.generator| variable. In order +// to handle this, we can't reuse the same TryCatch emitter. +// +// Simple case - For a function without expression parameters: +// `async function f(<params>) {<body>}`, +// AsyncEmitter ae(this); +// +// ae.prepareForParamsWithoutExpression(); +// // Emit Params. +// ... +// ae.paramsEpilogue(); // We need to emit the epilogue before the extra +// VarScope emitExtraBodyVarScope(); +// +// // Emit new scope +// ae.prepareForBody(); +// +// // Emit body of the Function. +// +// ae.emitEnd(); +// +// Complex case - For a function with expression parameters: +// `async function f(<expression>) {<body>}`, +// AsyncEmitter ae(this); +// +// ae.prepareForParamsWithExpression(); +// +// // Emit Params. +// ... +// ae.paramsEpilogue(); // We need to emit the epilogue before the extra +// // VarScope +// emitExtraBodyVarScope(); +// +// // Emit new scope +// ae.prepareForBody(); +// +// // Emit body of the Function. +// ... +// ae.emitEnd(); +// +// +// Async Module case - For a module with `await` in the top level: +// AsyncEmitter ae(this); +// ae.prepareForModule(); // prepareForModule is used to setup the generator +// // for the async module. +// switchToMain(); +// ... +// +// // Emit new scope +// ae.prepareForBody(); +// +// // Emit body of the Script. +// +// ae.emitEnd(); +// + +class MOZ_STACK_CLASS AsyncEmitter { + private: + BytecodeEmitter* bce_; + + // try-catch block for async function parameter and body. + mozilla::Maybe<TryEmitter> rejectTryCatch_; + +#ifdef DEBUG + // The state of this emitter. + // + // +-------+ + // | Start |-+ + // +-------+ | + // | + // +----------+ + // | + // | [Parameters with Expression] + // | prepareForParamsWithExpression +------------+ + // +-------------------------------------| Parameters |-->+ + // | +------------+ | + // | | + // | [Parameters Without Expression] | + // | prepareForParamsWithoutExpression +------------+ | + // +-------------------------------------| Parameters |-->+ + // | +------------+ | + // | [Modules] | + // | prepareForModule +----------------+ | + // +-------------------->| ModulePrologue |--+ | + // +----------------+ | | + // | | + // | | + // +-----------------------------------------+ | + // | | + // | | + // V +------------+ paramsEpilogue | + // +<--------------------| PostParams |<------------------+ + // | +------------+ + // | + // | [Script body] + // | prepareForBody +---------+ + // +-------------------->| Body |--------+ + // +---------+ | <emit script body> + // +----------------------------------------+ + // | + // | emitEnd +-----+ + // +--------------------->| End | + // +-----+ + + enum class State { + // The initial state. + Start, + + Parameters, + + ModulePrologue, + + PostParams, + + Body, + + End, + }; + + State state_ = State::Start; +#endif + + MOZ_MUST_USE bool emitRejectCatch(); + MOZ_MUST_USE bool emitFinalYield(); + + public: + explicit AsyncEmitter(BytecodeEmitter* bce) : bce_(bce){}; + + MOZ_MUST_USE bool prepareForParamsWithoutExpression(); + MOZ_MUST_USE bool prepareForParamsWithExpression(); + MOZ_MUST_USE bool prepareForModule(); + MOZ_MUST_USE bool emitParamsEpilogue(); + MOZ_MUST_USE bool prepareForBody(); + MOZ_MUST_USE bool emitEnd(); +}; + +} /* namespace frontend */ +} /* namespace js */ + +#endif /* frontend_AsyncEmitter_h */ |