ForOfEmitter.h (3879B)
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_ForOfEmitter_h 8 #define frontend_ForOfEmitter_h 9 10 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS 11 #include "mozilla/Maybe.h" // mozilla::Maybe 12 13 #include <stdint.h> // int32_t 14 15 #include "frontend/ForOfLoopControl.h" // ForOfLoopControl 16 #include "frontend/IteratorKind.h" // IteratorKind 17 #include "frontend/SelfHostedIter.h" // SelfHostedIter 18 #include "frontend/TDZCheckCache.h" // TDZCheckCache 19 20 namespace js { 21 namespace frontend { 22 23 struct BytecodeEmitter; 24 class EmitterScope; 25 26 // Class for emitting bytecode for for-of loop. 27 // 28 // Usage: (check for the return value is omitted for simplicity) 29 // 30 // `for (init of iterated) body` 31 // // headLexicalEmitterScope: lexical scope for init 32 // ForOfEmitter forOf(this, headLexicalEmitterScope); 33 // forOf.emitIterated(); 34 // emit(iterated); 35 // forOf.emitInitialize(offset_of_for); 36 // emit(init); 37 // forOf.emitBody(); 38 // emit(body); 39 // forOf.emitEnd(offset_of_iterated); 40 // 41 class MOZ_STACK_CLASS ForOfEmitter { 42 BytecodeEmitter* bce_; 43 44 #ifdef DEBUG 45 // The stack depth before emitting IteratorNext code inside loop. 46 int32_t loopDepth_ = 0; 47 #endif 48 49 SelfHostedIter selfHostedIter_; 50 IteratorKind iterKind_; 51 52 mozilla::Maybe<ForOfLoopControl> loopInfo_; 53 54 // The lexical scope to be freshened for each iteration. 55 // See the comment in `emitBody` for more details. 56 const EmitterScope* headLexicalEmitterScope_; 57 58 // Cache for the iterated value. 59 // (The cache for the iteration body is inside `loopInfo_`) 60 mozilla::Maybe<TDZCheckCache> tdzCacheForIteratedValue_; 61 62 #ifdef DEBUG 63 // The state of this emitter. 64 // 65 // +-------+ emitIterated +----------+ emitInitialize +------------+ 66 // | Start |------------->| Iterated |--------------->| Initialize |-+ 67 // +-------+ +----------+ +------------+ | 68 // | 69 // +----------------------------------+ 70 // | 71 // | emitBody +------+ emitEnd +-----+ 72 // +----------| Body |--------->| End | 73 // +------+ +-----+ 74 enum class State { 75 // The initial state. 76 Start, 77 78 // After calling emitIterated. 79 Iterated, 80 81 // After calling emitInitialize. 82 Initialize, 83 84 // After calling emitBody. 85 Body, 86 87 // After calling emitEnd. 88 End 89 }; 90 State state_ = State::Start; 91 #endif 92 93 public: 94 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 95 enum class HeadUsingDeclarationKind { None, Sync, Async }; 96 97 private: 98 HeadUsingDeclarationKind usingDeclarationInHead_ = 99 HeadUsingDeclarationKind::None; 100 101 public: 102 #endif 103 104 ForOfEmitter(BytecodeEmitter* bce, 105 const EmitterScope* headLexicalEmitterScope, 106 SelfHostedIter selfHostedIter, IteratorKind iterKind 107 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 108 , 109 HeadUsingDeclarationKind usingDeclarationInHead 110 #endif 111 ); 112 113 // The offset in the source code for each character below: 114 // 115 // for ( var x of obj ) { ... } 116 // ^ ^ 117 // | | 118 // | iteratedPos 119 // | 120 // forPos 121 [[nodiscard]] bool emitIterated(); 122 [[nodiscard]] bool emitInitialize(uint32_t forPos); 123 [[nodiscard]] bool emitBody(); 124 [[nodiscard]] bool emitEnd(uint32_t iteratedPos); 125 }; 126 127 } /* namespace frontend */ 128 } /* namespace js */ 129 130 #endif /* frontend_ForOfEmitter_h */