LexicalScopeEmitter.h (2930B)
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 frontend_LexicalScopeEmitter_h 8 #define frontend_LexicalScopeEmitter_h 9 10 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS 11 #include "mozilla/Maybe.h" // Maybe 12 13 #include "frontend/EmitterScope.h" // EmitterScope 14 #include "frontend/TDZCheckCache.h" // TDZCheckCache 15 #include "vm/Scope.h" // ScopeKind, LexicalScope 16 17 namespace js { 18 namespace frontend { 19 20 struct BytecodeEmitter; 21 22 // Class for emitting bytecode for lexical scope. 23 // 24 // In addition to emitting code for entering and leaving a scope, this RAII 25 // guard affects the code emitted for `break` and other non-structured 26 // control flow. See NonLocalExitControl::prepareForNonLocalJump(). 27 // 28 // Usage: (check for the return value is omitted for simplicity) 29 // 30 // `{ ... }` -- lexical scope with no bindings 31 // LexicalScopeEmitter lse(this); 32 // lse.emitEmptyScope(); 33 // emit(scopeBody); 34 // lse.emitEnd(); 35 // 36 // `{ let a; body }` 37 // LexicalScopeEmitter lse(this); 38 // lse.emitScope(ScopeKind::Lexical, scopeBinding); 39 // emit(let_and_body); 40 // lse.emitEnd(); 41 // 42 // `catch (e) { body }` 43 // LexicalScopeEmitter lse(this); 44 // lse.emitScope(ScopeKind::SimpleCatch, scopeBinding); 45 // emit(body); 46 // lse.emitEnd(); 47 // 48 // `catch ([a, b]) { body }` 49 // LexicalScopeEmitter lse(this); 50 // lse.emitScope(ScopeKind::Catch, scopeBinding); 51 // emit(body); 52 // lse.emitEnd(); 53 class MOZ_STACK_CLASS LexicalScopeEmitter { 54 BytecodeEmitter* bce_; 55 56 mozilla::Maybe<TDZCheckCache> tdzCache_; 57 mozilla::Maybe<EmitterScope> emitterScope_; 58 59 #ifdef DEBUG 60 // The state of this emitter. 61 // 62 // +-------+ emitScope +-------+ emitEnd +-----+ 63 // | Start |----------->| Scope |--------->| End | 64 // +-------+ +-------+ +-----+ 65 enum class State { 66 // The initial state. 67 Start, 68 69 // After calling emitScope/emitEmptyScope. 70 Scope, 71 72 // After calling emitEnd. 73 End, 74 }; 75 State state_ = State::Start; 76 #endif 77 78 public: 79 explicit LexicalScopeEmitter(BytecodeEmitter* bce); 80 81 // Returns the scope object for non-empty scope. 82 const EmitterScope& emitterScope() const { return *emitterScope_; } 83 84 [[nodiscard]] bool emitScope(ScopeKind kind, 85 LexicalScope::ParserData* bindings 86 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 87 , 88 BlockKind blockKind = BlockKind::Other 89 #endif 90 ); 91 [[nodiscard]] bool emitEmptyScope(); 92 93 [[nodiscard]] bool emitEnd(); 94 }; 95 96 } /* namespace frontend */ 97 } /* namespace js */ 98 99 #endif /* frontend_LexicalScopeEmitter_h */