Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/frontend/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  EmitterScope.h   Sprache: C

 
/* -*- 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_EmitterScope_h
#define frontend_EmitterScope_h

#include "mozilla/Maybe.h"

#include <stdint.h>

#include "ds/Nestable.h"
#include "frontend/AbstractScopePtr.h"
#include "frontend/NameAnalysisTypes.h"
#include "frontend/NameCollections.h"
#include "frontend/Stencil.h"
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
#  include "frontend/UsingEmitter.h"
#endif
#include "vm/Opcodes.h"        // JSOp
#include "vm/SharedStencil.h"  // GCThingIndex

namespace js {
namespace frontend {

struct BytecodeEmitter;
class EvalSharedContext;
class FunctionBox;
class GlobalSharedContext;
class ModuleSharedContext;
class TaggedParserAtomIndex;

// A scope that introduces bindings.
class EmitterScope : public Nestable<EmitterScope> {
  // The cache of bound names that may be looked up in the
  // scope. Initially populated as the set of names this scope binds. As
  // names are looked up in enclosing scopes, they are cached on the
  // current scope.
  PooledMapPtr<NameLocationMap> nameCache_;

  // If this scope's cache does not include free names, such as the
  // global scope, the NameLocation to return.
  mozilla::Maybe<NameLocation> fallbackFreeNameLocation_;

  // True if there is a corresponding EnvironmentObject on the environment
  // chain, false if all bindings are stored in frame slots on the stack.
  bool hasEnvironment_;

#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
  mozilla::Maybe<UsingEmitter> usingEmitter_;

  mozilla::Maybe<ForOfDisposalEmitter> forOfDisposalEmitter_;

 private:
  BlockKind blockKind_ = BlockKind::Other;
#endif

  // The number of enclosing environments. Used for error checking.
  uint8_t environmentChainLength_;

  // The next usable slot on the frame for not-closed over bindings.
  //
  // The initial frame slot when assigning slots to bindings is the
  // enclosing scope's nextFrameSlot. For the first scope in a frame,
  // the initial frame slot is 0.
  uint32_t nextFrameSlot_;

  // The index in the BytecodeEmitter's interned scope vector, otherwise
  // ScopeNote::NoScopeIndex.
  GCThingIndex scopeIndex_;

  // If kind is Lexical, Catch, or With, the index in the BytecodeEmitter's
  // block scope note list. Otherwise ScopeNote::NoScopeNote.
  uint32_t noteIndex_;

  [[nodiscard]] bool ensureCache(BytecodeEmitter* bce);

  [[nodiscard]] bool checkSlotLimits(BytecodeEmitter* bce,
                                     const ParserBindingIter& bi);

  [[nodiscard]] bool checkEnvironmentChainLength(BytecodeEmitter* bce);

  void updateFrameFixedSlots(BytecodeEmitter* bce, const ParserBindingIter& bi);

  [[nodiscard]] bool putNameInCache(BytecodeEmitter* bce,
                                    TaggedParserAtomIndex name,
                                    NameLocation loc);

  mozilla::Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce,
                                             TaggedParserAtomIndex name);

  EmitterScope* enclosing(BytecodeEmitter** bce) const;

  mozilla::Maybe<ScopeIndex> enclosingScopeIndex(BytecodeEmitter* bce) const;

  static bool nameCanBeFree(BytecodeEmitter* bce, TaggedParserAtomIndex name);

  NameLocation searchAndCache(BytecodeEmitter* bce, TaggedParserAtomIndex name);

  [[nodiscard]] bool internEmptyGlobalScopeAsBody(BytecodeEmitter* bce);

  [[nodiscard]] bool internScopeStencil(BytecodeEmitter* bce, ScopeIndex index);

  [[nodiscard]] bool internBodyScopeStencil(BytecodeEmitter* bce,
                                            ScopeIndex index);
  [[nodiscard]] bool appendScopeNote(BytecodeEmitter* bce);

  [[nodiscard]] bool clearFrameSlotRange(BytecodeEmitter* bce, JSOp opcode,
                                         uint32_t slotStart,
                                         uint32_t slotEnd) const;

  [[nodiscard]] bool deadZoneFrameSlotRange(BytecodeEmitter* bce,
                                            uint32_t slotStart,
                                            uint32_t slotEnd) const {
    return clearFrameSlotRange(bce, JSOp::Uninitialized, slotStart, slotEnd);
  }

#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
  void setHasDisposables(BytecodeEmitter* bce) {
    if (!usingEmitter_.isSome()) {
      usingEmitter_.emplace(bce);
    }
  }
#endif

 public:
  explicit EmitterScope(BytecodeEmitter* bce);

  void dump(BytecodeEmitter* bce);

  [[nodiscard]] bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
                                  LexicalScope::ParserData* bindings
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
                                  ,
                                  BlockKind blockKind = BlockKind::Other
#endif
  );
  [[nodiscard]] bool enterClassBody(BytecodeEmitter* bce, ScopeKind kind,
                                    ClassBodyScope::ParserData* bindings);
  [[nodiscard]] bool enterNamedLambda(BytecodeEmitter* bce,
                                      FunctionBox* funbox);
  [[nodiscard]] bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
  [[nodiscard]] bool enterFunctionExtraBodyVar(BytecodeEmitter* bce,
                                               FunctionBox* funbox);
  [[nodiscard]] bool enterGlobal(BytecodeEmitter* bce,
                                 GlobalSharedContext* globalsc);
  [[nodiscard]] bool enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc);
  [[nodiscard]] bool enterModule(BytecodeEmitter* module,
                                 ModuleSharedContext* modulesc);
  [[nodiscard]] bool enterWith(BytecodeEmitter* bce);
  [[nodiscard]] bool deadZoneFrameSlots(BytecodeEmitter* bce) const;

  [[nodiscard]] bool leave(BytecodeEmitter* bce, bool nonLocal = false);

  GCThingIndex index() const {
    MOZ_ASSERT(scopeIndex_ != ScopeNote::NoScopeIndex,
               "Did you forget to intern a Scope?");
    return scopeIndex_;
  }

  uint32_t noteIndex() const { return noteIndex_; }

  AbstractScopePtr scope(const BytecodeEmitter* bce) const;
  mozilla::Maybe<ScopeIndex> scopeIndex(const BytecodeEmitter* bce) const;

  bool hasEnvironment() const { return hasEnvironment_; }

#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
 private:
  // Disposable Scope here refers to any scope
  // with using bindings in it for now that is
  // a lexical scope and a module scope.
  [[nodiscard]] bool prepareForDisposableScopeBody(BytecodeEmitter* bce);

  [[nodiscard]] bool emitSwitchBlockEndForDisposableScopeBodyEnd(
      BytecodeEmitter* bce);

  [[nodiscard]] bool emitDisposableScopeBodyEnd(BytecodeEmitter* bce);

  [[nodiscard]] bool emitDisposableScopeBodyEndForNonLocalJump(
      BytecodeEmitter* bce);

 public:
  [[nodiscard]] bool prepareForModuleDisposableScopeBody(BytecodeEmitter* bce);

  [[nodiscard]] bool emitModuleDisposableScopeBodyEnd(BytecodeEmitter* bce);

  [[nodiscard]] bool prepareForDisposableAssignment(UsingHint hint);

  bool hasDisposables() const { return usingEmitter_.isSome(); }

  bool hasAsyncDisposables() const {
    return hasDisposables() && usingEmitter_->hasAwaitUsing();
  }
#endif

  // The first frame slot used.
  uint32_t frameSlotStart() const {
    if (EmitterScope* inFrame = enclosingInFrame()) {
      return inFrame->nextFrameSlot_;
    }
    return 0;
  }

  // The last frame slot used + 1.
  uint32_t frameSlotEnd() const { return nextFrameSlot_; }

  EmitterScope* enclosingInFrame() const {
    return Nestable<EmitterScope>::enclosing();
  }

  NameLocation lookup(BytecodeEmitter* bce, TaggedParserAtomIndex name);

  // Find both the slot associated with a private name and the location of the
  // corresponding `.privateBrand` binding.
  //
  // Simply doing two separate lookups, one for `name` and another for
  // `.privateBrand`, would give the wrong answer in this case:
  //
  //     class Outer {
  //       #outerMethod() { reutrn "ok"; }
  //
  //       test() {
  //         class Inner {
  //           #innerMethod() {}
  //           test(outer) {
  //             return outer.#outerMethod();
  //           }
  //         }
  //         return new Inner().test(this);
  //       }
  //     }
  //
  //    new Outer().test();  // should return "ok"
  //
  // At the point in Inner.test where `#outerMethod` is called, we need to
  // check for the private brand of `Outer`, not `Inner`; but both class bodies
  // have `.privateBrand` bindings. In a normal `lookup`, the inner binding
  // would shadow the outer one.
  //
  // This method instead sets `brandLoc` to the location of the `.privateBrand`
  // binding in the same class body as the private name `name`, ignoring
  // shadowing. If `name` refers to a name that is actually stamped onto the
  // target object (anything other than a non-static private method), then
  // `brandLoc` is set to Nothing.
  void lookupPrivate(BytecodeEmitter* bce, TaggedParserAtomIndex name,
                     NameLocation& loc, mozilla::Maybe<NameLocation>& brandLoc);

  mozilla::Maybe<NameLocation> locationBoundInScope(TaggedParserAtomIndex name,
                                                    EmitterScope* target);

  // For a given emitter scope, return the number of enclosing environments in
  // the current compilation (this excludes environments that could enclose the
  // compilation, like would happen for an eval copmilation).
  static uint32_t CountEnclosingCompilationEnvironments(
      BytecodeEmitter* bce, EmitterScope* emitterScope);
};

/* namespace frontend */
/* namespace js */

#endif /* frontend_EmitterScope_h */

Messung V0.5
C=89 H=99 G=94

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.