Issue #2155 - Split Nestable to ds/ and EmitterScope to EmitterScope.{cpp.h}

Based-on: m-c 1351107/17, m-c 1460489/2
This commit is contained in:
Martok 2023-03-23 23:24:00 +01:00 committed by roytam1
commit 81691afbc3
9 changed files with 1323 additions and 1218 deletions

66
js/src/ds/Nestable.h Normal file
View file

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 ds_Nestable_h
#define ds_Nestable_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
namespace js {
// A base class for nestable structures.
template <typename Concrete>
class MOZ_STACK_CLASS Nestable
{
Concrete** stack_;
Concrete* enclosing_;
protected:
explicit Nestable(Concrete** stack)
: stack_(stack),
enclosing_(*stack)
{
*stack_ = static_cast<Concrete*>(this);
}
// These method are protected. Some derived classes, such as ParseContext,
// do not expose the ability to walk the stack.
Concrete* enclosing() const {
return enclosing_;
}
template <typename Predicate /* (Concrete*) -> bool */>
static Concrete* findNearest(Concrete* it, Predicate predicate) {
while (it && !predicate(it))
it = it->enclosing();
return it;
}
template <typename T>
static T* findNearest(Concrete* it) {
while (it && !it->template is<T>())
it = it->enclosing();
return it ? &it->template as<T>() : nullptr;
}
template <typename T, typename Predicate /* (T*) -> bool */>
static T* findNearest(Concrete* it, Predicate predicate) {
while (it && (!it->template is<T>() || !predicate(&it->template as<T>())))
it = it->enclosing();
return it ? &it->template as<T>() : nullptr;
}
public:
~Nestable() {
MOZ_ASSERT(*stack_ == static_cast<Concrete*>(this));
*stack_ = enclosing_;
}
};
} // namespace js
#endif /* ds_Nestable_h */

File diff suppressed because it is too large Load diff

View file

@ -122,13 +122,13 @@ typedef Vector<jssrcnote, 64> SrcNotesVector;
class CallOrNewEmitter;
class ElemOpEmitter;
class EmitterScope;
class PropOpEmitter;
class TDZCheckCache;
struct MOZ_STACK_CLASS BytecodeEmitter
{
class NestableControl;
class EmitterScope;
SharedContext* const sc; /* context shared between parsing and bytecode generation */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/NameAnalysisTypes.h"
#include "frontend/NameCollections.h"
#include "frontend/SharedContext.h"
#include "jstypes.h"
#include "vm/Scope.h"
namespace js {
namespace frontend {
// 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.
uint32_t 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);
template <typename BindingIter>
MOZ_MUST_USE bool checkSlotLimits(BytecodeEmitter* bce, const BindingIter& bi);
MOZ_MUST_USE bool checkEnvironmentChainLength(BytecodeEmitter* bce);
void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi);
MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name, NameLocation loc);
mozilla::Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce, JSAtom* name);
EmitterScope* enclosing(BytecodeEmitter** bce) const;
Scope* enclosingScope(BytecodeEmitter* bce) const;
static bool nameCanBeFree(BytecodeEmitter* bce, JSAtom* name);
static NameLocation searchInEnclosingScope(JSAtom* name, Scope* scope, uint8_t hops);
NameLocation searchAndCache(BytecodeEmitter* bce, JSAtom* name);
template <typename ScopeCreator>
MOZ_MUST_USE bool internScope(BytecodeEmitter* bce, ScopeCreator createScope);
template <typename ScopeCreator>
MOZ_MUST_USE bool internBodyScope(BytecodeEmitter* bce, ScopeCreator createScope);
MOZ_MUST_USE bool appendScopeNote(BytecodeEmitter* bce);
MOZ_MUST_USE bool deadZoneFrameSlotRange(BytecodeEmitter* bce, uint32_t slotStart,
uint32_t slotEnd);
public:
explicit EmitterScope(BytecodeEmitter* bce);
void dump(BytecodeEmitter* bce);
MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
Handle<LexicalScope::Data*> bindings);
MOZ_MUST_USE bool enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox);
MOZ_MUST_USE bool enterComprehensionFor(BytecodeEmitter* bce,
Handle<LexicalScope::Data*> bindings);
MOZ_MUST_USE bool enterFunction(BytecodeEmitter* bce, FunctionBox* funbox);
MOZ_MUST_USE bool enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox);
MOZ_MUST_USE bool enterParameterExpressionVar(BytecodeEmitter* bce);
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);
MOZ_MUST_USE bool leave(BytecodeEmitter* bce, bool nonLocal = false);
uint32_t index() const {
MOZ_ASSERT(scopeIndex_ != ScopeNote::NoScopeIndex, "Did you forget to intern a Scope?");
return scopeIndex_;
}
uint32_t noteIndex() const {
return noteIndex_;
}
Scope* scope(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_;
}
uint32_t numFrameSlots() const {
return frameSlotEnd() - frameSlotStart();
}
EmitterScope* enclosingInFrame() const {
return Nestable<EmitterScope>::enclosing();
}
NameLocation lookup(BytecodeEmitter* bce, JSAtom* name);
mozilla::Maybe<NameLocation> locationBoundInScope(JSAtom* name, EmitterScope* target);
};
} /* namespace frontend */
} /* namespace js */
#endif /* frontend_EmitterScope_h */

View file

@ -14,6 +14,7 @@
#include "jsiter.h"
#include "jspubtd.h"
#include "ds/Nestable.h"
#include "frontend/BytecodeCompiler.h"
#include "frontend/FullParseHandler.h"
#include "frontend/NameAnalysisTypes.h"

View file

@ -60,56 +60,6 @@ StatementKindIsUnlabeledBreakTarget(StatementKind kind)
return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
}
// A base class for nestable structures in the frontend, such as statements
// and scopes.
template <typename Concrete>
class MOZ_STACK_CLASS Nestable
{
Concrete** stack_;
Concrete* enclosing_;
protected:
explicit Nestable(Concrete** stack)
: stack_(stack),
enclosing_(*stack)
{
*stack_ = static_cast<Concrete*>(this);
}
// These method are protected. Some derived classes, such as ParseContext,
// do not expose the ability to walk the stack.
Concrete* enclosing() const {
return enclosing_;
}
template <typename Predicate /* (Concrete*) -> bool */>
static Concrete* findNearest(Concrete* it, Predicate predicate) {
while (it && !predicate(it))
it = it->enclosing();
return it;
}
template <typename T>
static T* findNearest(Concrete* it) {
while (it && !it->template is<T>())
it = it->enclosing();
return it ? &it->template as<T>() : nullptr;
}
template <typename T, typename Predicate /* (T*) -> bool */>
static T* findNearest(Concrete* it, Predicate predicate) {
while (it && (!it->template is<T>() || !predicate(&it->template as<T>())))
it = it->enclosing();
return it ? &it->template as<T>() : nullptr;
}
public:
~Nestable() {
MOZ_ASSERT(*stack_ == static_cast<Concrete*>(this));
*stack_ = enclosing_;
}
};
// These flags apply to both global and function contexts.
class AnyContextFlags
{

View file

@ -10,7 +10,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "frontend/SharedContext.h" // for Nestable
#include "ds/Nestable.h"
#include "frontend/NameCollections.h"
#include "js/TypeDecls.h"
#include "vm/Stack.h"

View file

@ -142,6 +142,7 @@ UNIFIED_SOURCES += [
'frontend/BytecodeEmitter.cpp',
'frontend/CallOrNewEmitter.cpp',
'frontend/ElemOpEmitter.cpp',
'frontend/EmitterScope.cpp',
'frontend/FoldConstants.cpp',
'frontend/IfEmitter.cpp',
'frontend/JumpList.cpp',