/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Class for emitting bytecode for c-style for block. // // Usage: (check for the return value is omitted for simplicity) // // `for (init; cond; update) body` // CForEmitter cfor(this, headLexicalEmitterScopeForLet or nullptr); // cfor.emitInit(Some(offset_of_init)); // emit(init); // without pushing value // cfor.emitCond(Some(offset_of_cond)); // emit(cond); // cfor.emitBody(CForEmitter::Cond::Present); // emit(body); // cfor.emitUpdate(CForEmitter::Update::Present, Some(offset_of_update))); // emit(update); // cfor.emitEnd(offset_of_for); // // `for (;;) body` // CForEmitter cfor(this, nullptr); // cfor.emitInit(Nothing()); // cfor.emitCond(Nothing()); // cfor.emitBody(CForEmitter::Cond::Missing); // emit(body); // cfor.emitUpdate(CForEmitter::Update::Missing, Nothing()); // cfor.emitEnd(offset_of_for); // class MOZ_STACK_CLASS CForEmitter { // Basic structure of the bytecode (not complete). // // If `cond` is not empty: // {init} // loop: // JSOp::LoopHead // {cond} // JSOp::JumpIfFalse break // {body} // continue: // {update} // JSOp::Goto loop // break: // // If `cond` is empty: // {init} // loop: // JSOp::LoopHead // {body} // continue: // {update} // JSOp::Goto loop // break: // public: enumclass Cond { Missing, Present }; enumclass Update { Missing, Present };
private:
BytecodeEmitter* bce_;
// Whether the c-style for loop has `cond` and `update`.
Cond cond_ = Cond::Missing;
Update update_ = Update::Missing;
mozilla::Maybe<LoopControl> loopInfo_;
// The lexical scope to be freshened for each iteration. // See the comment in `emitCond` for more details. // // ### Scope freshening // // Each iteration of a `for (let V...)` loop creates a fresh loop variable
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10 // // var funcs = []; // for (let i = 0; i < 2; i++) // funcs.push(function() { return i; }); // assertEq(funcs[0](), 0); // the two closures capture... // assertEq(funcs[1](), 1); // ...two different `i` bindings // // This is implemented by "freshening" the implicit block -- changing the [[ **-c^ **-cb ^*^****^**, // scope chain to a fresh clone of the instantaneous block object -- each // iteration, just before evaluating the "update" in for(;;) loops. // // ECMAScript doesn't freshen in `for (const ...;;)`. Lack of freshening // isn't directly observable in-language because `const`s can't be mutated, // but it *can* be observed in the Debugger API. const EmitterScope* headLexicalEmitterScopeForLet_;
mozilla::Maybe<TDZCheckCache> tdzCache_;
#ifdef DEBUG // The state of this emitter. // // +-------+ emitInit +------+ emitCond +------+ emitBody +------+ // | Start |--------->| Init |--------->| Cond |--------->| Body |-+ // +-------+ +------+ +------+ +------+ | // | // +-------------------------------------+ // | // | emitUpdate +--------+ emitEnd +-----+ // +----------->| Update |-------->| End | // +--------+ +-----+ enumclass State { // The initial state.
Start,
// After calling emitInit.
Init,
// After calling emitCond.
Cond,
// After calling emitBody.
Body,
// After calling emitUpdate.
Update,
// After calling emitEnd.
End
};
State state_ = State::Start; #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.