summaryrefslogtreecommitdiffstats
path: root/js/src/frontend/EmitterScope.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/frontend/EmitterScope.h
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/frontend/EmitterScope.h')
-rw-r--r--js/src/frontend/EmitterScope.h171
1 files changed, 171 insertions, 0 deletions
diff --git a/js/src/frontend/EmitterScope.h b/js/src/frontend/EmitterScope.h
new file mode 100644
index 0000000000..fe726cd0e7
--- /dev/null
+++ b/js/src/frontend/EmitterScope.h
@@ -0,0 +1,171 @@
+/* -*- 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/Attributes.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/ParseContext.h"
+#include "frontend/SharedContext.h"
+#include "js/TypeDecls.h"
+#include "vm/BytecodeUtil.h" // JSOp
+#include "vm/SharedStencil.h" // GCThingIndex
+
+namespace js {
+
+class Scope;
+
+namespace frontend {
+
+struct BytecodeEmitter;
+
+// 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_;
+
+ // 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_;
+
+ MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce);
+
+ MOZ_MUST_USE bool checkSlotLimits(BytecodeEmitter* bce,
+ const ParserBindingIter& bi);
+
+ MOZ_MUST_USE bool checkEnvironmentChainLength(BytecodeEmitter* bce);
+
+ void updateFrameFixedSlots(BytecodeEmitter* bce, const ParserBindingIter& bi);
+
+ MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, const ParserAtom* name,
+ NameLocation loc);
+
+ mozilla::Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce,
+ const ParserAtom* name);
+
+ EmitterScope* enclosing(BytecodeEmitter** bce) const;
+
+ mozilla::Maybe<ScopeIndex> enclosingScopeIndex(BytecodeEmitter* bce) const;
+
+ static bool nameCanBeFree(BytecodeEmitter* bce, const ParserAtom* name);
+
+ static NameLocation searchInEnclosingScope(JSAtom* name, Scope* scope,
+ uint8_t hops);
+ NameLocation searchAndCache(BytecodeEmitter* bce, const ParserAtom* name);
+
+ MOZ_MUST_USE bool internEmptyGlobalScopeAsBody(BytecodeEmitter* bce);
+
+ template <typename ScopeCreator>
+ MOZ_MUST_USE bool internScopeCreationData(BytecodeEmitter* bce,
+ ScopeCreator createScope);
+
+ template <typename ScopeCreator>
+ MOZ_MUST_USE bool internBodyScopeCreationData(BytecodeEmitter* bce,
+ ScopeCreator createScope);
+ MOZ_MUST_USE bool appendScopeNote(BytecodeEmitter* bce);
+
+ MOZ_MUST_USE bool clearFrameSlotRange(BytecodeEmitter* bce, JSOp opcode,
+ uint32_t slotStart,
+ uint32_t slotEnd) const;
+
+ MOZ_MUST_USE bool deadZoneFrameSlotRange(BytecodeEmitter* bce,
+ uint32_t slotStart,
+ uint32_t slotEnd) const {
+ return clearFrameSlotRange(bce, JSOp::Uninitialized, slotStart, slotEnd);
+ }
+
+ public:
+ explicit EmitterScope(BytecodeEmitter* bce);
+
+ void dump(BytecodeEmitter* bce);
+
+ MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
+ LexicalScope::ParserData* bindings);
+ MOZ_MUST_USE bool enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox);
+ MOZ_MUST_USE bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
+ MOZ_MUST_USE bool enterFunctionExtraBodyVar(BytecodeEmitter* bce,
+ FunctionBox* funbox);
+ MOZ_MUST_USE bool enterGlobal(BytecodeEmitter* bce,
+ GlobalSharedContext* globalsc);
+ MOZ_MUST_USE bool enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc);
+ MOZ_MUST_USE bool enterModule(BytecodeEmitter* module,
+ ModuleSharedContext* modulesc);
+ MOZ_MUST_USE bool enterWith(BytecodeEmitter* bce);
+ MOZ_MUST_USE bool deadZoneFrameSlots(BytecodeEmitter* bce) const;
+
+ MOZ_MUST_USE 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_; }
+
+ // 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, const ParserAtom* name);
+
+ mozilla::Maybe<NameLocation> locationBoundInScope(const ParserAtom* name,
+ EmitterScope* target);
+};
+
+} /* namespace frontend */
+} /* namespace js */
+
+#endif /* frontend_EmitterScope_h */