mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1660699 - Store JSAtom in CompilationInfo. r=tcampbell
ParserAtom now holds either AtomIndex that is an index into CompilationInfo.atoms, or WellKnownAtomId that maps to cx->names() fields. ParserAtoms in WellKnownParserAtoms holds WellKnownAtomId, and ParserAtoms in CompilationInfo.parserAtoms holds AtomIndex. GetWellKnownAtom relies on the struct layout of JSAtomState, to quickly map WellKnownParserAtoms to its field. Differential Revision: https://phabricator.services.mozilla.com/D88203
This commit is contained in:
parent
3742f3b6f0
commit
90a2e27cb6
@ -58,7 +58,7 @@ bool js::frontend::EmitScriptThingsVector(JSContext* cx,
|
||||
mozilla::Span<JS::GCCellPtr>& output;
|
||||
|
||||
bool operator()(const ScriptAtom& data) {
|
||||
auto maybeAtom = data->toJSAtom(cx);
|
||||
auto maybeAtom = data->toJSAtom(cx, compilationInfo);
|
||||
if (maybeAtom.isErr()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -165,6 +165,8 @@ struct MOZ_RAII CompilationInfo {
|
||||
// Table of parser atoms for this compilation.
|
||||
ParserAtomsTable parserAtoms;
|
||||
|
||||
JS::RootedVector<JSAtom*> atoms;
|
||||
|
||||
Directives directives;
|
||||
|
||||
ScopeContext scopeContext;
|
||||
@ -238,6 +240,7 @@ struct MOZ_RAII CompilationInfo {
|
||||
options(options),
|
||||
keepAtoms(cx),
|
||||
parserAtoms(cx),
|
||||
atoms(cx),
|
||||
directives(options.forceStrictMode()),
|
||||
scopeContext(cx, enclosingScope, enclosingEnv),
|
||||
script(cx),
|
||||
@ -286,10 +289,10 @@ struct MOZ_RAII CompilationInfo {
|
||||
MOZ_MUST_USE bool instantiateStencils();
|
||||
|
||||
JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
|
||||
return parserAtom->toJSAtom(cx).unwrapOr(nullptr);
|
||||
return parserAtom->toJSAtom(cx, *this).unwrapOr(nullptr);
|
||||
}
|
||||
const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
|
||||
auto result = parserAtoms.internJSAtom(cx, atom);
|
||||
auto result = parserAtoms.internJSAtom(cx, *this, atom);
|
||||
return result.unwrapOr(nullptr);
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ bool ParseContext::isVarRedeclaredInEval(const ParserName* name,
|
||||
MOZ_ASSERT(sc()->isEvalContext());
|
||||
|
||||
// TODO-Stencil: After scope snapshotting, this can be done away with.
|
||||
auto mbNameAtom = name->toJSAtom(sc()->cx_);
|
||||
auto mbNameAtom = name->toJSAtom(sc()->cx_, sc()->compilationInfo());
|
||||
if (mbNameAtom.isErr()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -832,7 +832,8 @@ bool PerHandlerParser<ParseHandler>::
|
||||
// TODO-Stencil
|
||||
// After closed-over-bindings are snapshotted in the handler,
|
||||
// remove this.
|
||||
auto mbNameId = compilationInfo_.parserAtoms.internJSAtom(cx_, name);
|
||||
auto mbNameId = compilationInfo_.parserAtoms.internJSAtom(
|
||||
cx_, this->getCompilationInfo(), name);
|
||||
if (mbNameId.isErr()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "jsnum.h"
|
||||
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "frontend/NameCollections.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/Printer.h"
|
||||
@ -24,6 +25,27 @@ namespace frontend {
|
||||
|
||||
static JS::OOM PARSER_ATOMS_OOM;
|
||||
|
||||
static JSAtom* GetWellKnownAtom(JSContext* cx, WellKnownAtomId kind) {
|
||||
#define ASSERT_OFFSET_(idpart, id, text) \
|
||||
static_assert(offsetof(JSAtomState, id) == \
|
||||
int32_t(WellKnownAtomId::id) * \
|
||||
sizeof(js::ImmutablePropertyNamePtr));
|
||||
FOR_EACH_COMMON_PROPERTYNAME(ASSERT_OFFSET_);
|
||||
#undef ASSERT_OFFSET_
|
||||
|
||||
#define ASSERT_OFFSET_(name, clasp) \
|
||||
static_assert(offsetof(JSAtomState, name) == \
|
||||
int32_t(WellKnownAtomId::name) * \
|
||||
sizeof(js::ImmutablePropertyNamePtr));
|
||||
JS_FOR_EACH_PROTOTYPE(ASSERT_OFFSET_);
|
||||
#undef ASSERT_OFFSET_
|
||||
|
||||
static_assert(int32_t(WellKnownAtomId::abort) == 0,
|
||||
"Unexpected order of WellKnownAtom");
|
||||
|
||||
return (&cx->names().abort)[int32_t(kind)];
|
||||
}
|
||||
|
||||
mozilla::GenericErrorResult<OOM&> RaiseParserAtomsOOMError(JSContext* cx) {
|
||||
js::ReportOutOfMemory(cx);
|
||||
return mozilla::Err(PARSER_ATOMS_OOM);
|
||||
@ -66,12 +88,6 @@ ParserAtomEntry::allocateInline(JSContext* cx,
|
||||
}
|
||||
|
||||
bool ParserAtomEntry::equalsJSAtom(JSAtom* other) const {
|
||||
// If this parser-atom has already been atomized, or been constructed
|
||||
// from an existing js-atom, just compare against that.
|
||||
if (jsatom_) {
|
||||
return other == jsatom_;
|
||||
}
|
||||
|
||||
// Compare hashes and lengths first.
|
||||
if (hash_ != other->hash() || length_ != other->length()) {
|
||||
return false;
|
||||
@ -127,20 +143,30 @@ bool ParserAtomEntry::isIndex(uint32_t* indexp) const {
|
||||
js::CheckStringIsIndex(twoByteChars(), len, indexp);
|
||||
}
|
||||
|
||||
JS::Result<JSAtom*, OOM&> ParserAtomEntry::toJSAtom(JSContext* cx) const {
|
||||
if (jsatom_) {
|
||||
return jsatom_;
|
||||
JS::Result<JSAtom*, OOM&> ParserAtomEntry::toJSAtom(
|
||||
JSContext* cx, CompilationInfo& compilationInfo) const {
|
||||
if (atomIndex_.constructed<AtomIndex>()) {
|
||||
return compilationInfo.atoms[atomIndex_.ref<AtomIndex>()].get();
|
||||
}
|
||||
if (atomIndex_.constructed<WellKnownAtomId>()) {
|
||||
return GetWellKnownAtom(cx, atomIndex_.ref<WellKnownAtomId>());
|
||||
}
|
||||
|
||||
JSAtom* atom;
|
||||
if (hasLatin1Chars()) {
|
||||
jsatom_ = AtomizeChars(cx, latin1Chars(), length());
|
||||
atom = AtomizeChars(cx, latin1Chars(), length());
|
||||
} else {
|
||||
jsatom_ = AtomizeChars(cx, twoByteChars(), length());
|
||||
atom = AtomizeChars(cx, twoByteChars(), length());
|
||||
}
|
||||
if (!jsatom_) {
|
||||
if (!atom) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
return jsatom_;
|
||||
auto index = compilationInfo.atoms.length();
|
||||
if (!compilationInfo.atoms.append(atom)) {
|
||||
return mozilla::Err(PARSER_ATOMS_OOM);
|
||||
}
|
||||
atomIndex_.construct<AtomIndex>(index);
|
||||
return atom;
|
||||
}
|
||||
|
||||
bool ParserAtomEntry::toNumber(JSContext* cx, double* result) const {
|
||||
@ -302,18 +328,40 @@ JS::Result<const ParserAtom*, OOM&> ParserAtomsTable::internUtf8(
|
||||
}
|
||||
|
||||
JS::Result<const ParserAtom*, OOM&> ParserAtomsTable::internJSAtom(
|
||||
JSContext* cx, JSAtom* atom) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
JSContext* cx, CompilationInfo& compilationInfo, JSAtom* atom) {
|
||||
const ParserAtom* id;
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
||||
auto result =
|
||||
atom->hasLatin1Chars()
|
||||
? internLatin1(cx, atom->latin1Chars(nogc), atom->length())
|
||||
: internChar16(cx, atom->twoByteChars(nogc), atom->length());
|
||||
if (result.isErr()) {
|
||||
return result;
|
||||
auto result =
|
||||
atom->hasLatin1Chars()
|
||||
? internLatin1(cx, atom->latin1Chars(nogc), atom->length())
|
||||
: internChar16(cx, atom->twoByteChars(nogc), atom->length());
|
||||
if (result.isErr()) {
|
||||
return result;
|
||||
}
|
||||
id = result.unwrap();
|
||||
}
|
||||
|
||||
if (id->atomIndex_.empty()) {
|
||||
MOZ_ASSERT(id->equalsJSAtom(atom));
|
||||
|
||||
auto index = AtomIndex(compilationInfo.atoms.length());
|
||||
if (!compilationInfo.atoms.append(atom)) {
|
||||
return mozilla::Err(PARSER_ATOMS_OOM);
|
||||
}
|
||||
id->setAtomIndex(index);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
if (id->atomIndex_.constructed<AtomIndex>()) {
|
||||
MOZ_ASSERT(compilationInfo.atoms[id->atomIndex_.ref<AtomIndex>()] ==
|
||||
atom);
|
||||
} else {
|
||||
MOZ_ASSERT(GetWellKnownAtom(cx, id->atomIndex_.ref<WellKnownAtomId>()) ==
|
||||
atom);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
const ParserAtom* id = result.unwrap();
|
||||
id->setAtom(atom);
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -439,7 +487,7 @@ const ParserAtom* WellKnownParserAtoms::lookupChar16Seq(
|
||||
}
|
||||
|
||||
bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
||||
const char* str, JSAtom* jsatom) {
|
||||
const char* str, WellKnownAtomId kind) {
|
||||
MOZ_ASSERT(name != nullptr);
|
||||
|
||||
unsigned int len = strlen(str);
|
||||
@ -476,7 +524,7 @@ bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
||||
}
|
||||
entry = maybeEntry.unwrap();
|
||||
}
|
||||
entry->jsatom_ = jsatom;
|
||||
entry->setWellKnownAtomId(kind);
|
||||
|
||||
// Save name for returning after moving entry into set.
|
||||
const ParserName* nm = entry.get()->asName();
|
||||
@ -489,16 +537,16 @@ bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
||||
}
|
||||
|
||||
bool WellKnownParserAtoms::init(JSContext* cx) {
|
||||
#define COMMON_NAME_INIT_(idpart, id, text) \
|
||||
if (!initSingle(cx, &(id), text, cx->names().id)) { \
|
||||
return false; \
|
||||
#define COMMON_NAME_INIT_(idpart, id, text) \
|
||||
if (!initSingle(cx, &(id), text, WellKnownAtomId::id)) { \
|
||||
return false; \
|
||||
}
|
||||
FOR_EACH_COMMON_PROPERTYNAME(COMMON_NAME_INIT_)
|
||||
#undef COMMON_NAME_INIT_
|
||||
|
||||
#define COMMON_NAME_INIT_(name, clasp) \
|
||||
if (!initSingle(cx, &(name), #name, cx->names().name)) { \
|
||||
return false; \
|
||||
#define COMMON_NAME_INIT_(name, clasp) \
|
||||
if (!initSingle(cx, &(name), #name, WellKnownAtomId::name)) { \
|
||||
return false; \
|
||||
}
|
||||
JS_FOR_EACH_PROTOTYPE(COMMON_NAME_INIT_)
|
||||
#undef COMMON_NAME_INIT_
|
||||
|
@ -9,19 +9,22 @@
|
||||
|
||||
#include "mozilla/DebugOnly.h" // mozilla::DebugOnly
|
||||
#include "mozilla/HashFunctions.h" // HashString
|
||||
#include "mozilla/MaybeOneOf.h" // mozilla::MaybeOneOf
|
||||
#include "mozilla/Range.h" // mozilla::Range
|
||||
#include "mozilla/Variant.h" // mozilla::Variant
|
||||
|
||||
#include "ds/LifoAlloc.h" // LifoAlloc
|
||||
#include "js/HashTable.h" // HashSet
|
||||
#include "js/UniquePtr.h" // js::UniquePtr
|
||||
#include "js/Vector.h" // Vector
|
||||
#include "ds/LifoAlloc.h" // LifoAlloc
|
||||
#include "frontend/TypedIndex.h" // TypedIndex
|
||||
#include "js/HashTable.h" // HashSet
|
||||
#include "js/UniquePtr.h" // js::UniquePtr
|
||||
#include "js/Vector.h" // Vector
|
||||
#include "vm/CommonPropertyNames.h"
|
||||
#include "vm/StringType.h" // CompareChars, StringEqualsAscii
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
struct CompilationInfo;
|
||||
class ParserAtom;
|
||||
class ParserName;
|
||||
|
||||
@ -32,6 +35,25 @@ class ParserAtomsTable;
|
||||
|
||||
mozilla::GenericErrorResult<OOM&> RaiseParserAtomsOOMError(JSContext* cx);
|
||||
|
||||
// An index into CompilationInfo.atoms.
|
||||
// This is local to the current compilation.
|
||||
using AtomIndex = TypedIndex<JSAtom*>;
|
||||
|
||||
// An index to map WellKnownParserAtoms to cx->names().
|
||||
// This is consistent across multiple compilation.
|
||||
//
|
||||
// GetWellKnownAtom in ParserAtom.cpp relies on the fact that
|
||||
// JSAtomState fields and this enum variants use the same order.
|
||||
enum class WellKnownAtomId : uint32_t {
|
||||
#define ENUM_ENTRY_(idpart, id, text) id,
|
||||
FOR_EACH_COMMON_PROPERTYNAME(ENUM_ENTRY_)
|
||||
#undef ENUM_ENTRY_
|
||||
|
||||
#define ENUM_ENTRY_(name, clasp) name,
|
||||
JS_FOR_EACH_PROTOTYPE(ENUM_ENTRY_)
|
||||
#undef ENUM_ENTRY_
|
||||
};
|
||||
|
||||
/**
|
||||
* A ParserAtomEntry is an in-parser representation of an interned atomic
|
||||
* string. It mostly mirrors the information carried by a JSAtom*.
|
||||
@ -190,13 +212,13 @@ class alignas(alignof(void*)) ParserAtomEntry {
|
||||
HashNumber hash_;
|
||||
|
||||
// Used to dynamically optimize the mapping of ParserAtoms to JSAtom*s.
|
||||
// If the entry comes from an atom or has been mapped to an
|
||||
// atom previously, the atom reference is kept here.
|
||||
//
|
||||
// Note: if/when this field is removed, remove the comment
|
||||
// in front of the call to `rt->initializeParserAtoms()` in
|
||||
// `JS::InitSelfHostedCode`.
|
||||
mutable JSAtom* jsatom_ = nullptr;
|
||||
// If this ParserAtomEntry is a part of WellKnownParserAtoms, this should
|
||||
// hold WellKnownAtomId that maps to an item in cx->names().
|
||||
//
|
||||
// Otherwise, this should hold AtomIndex into CompilationInfo.atoms,
|
||||
// or empty if the JSAtom isn't yet allocated.
|
||||
mutable mozilla::MaybeOneOf<AtomIndex, WellKnownAtomId> atomIndex_;
|
||||
|
||||
public:
|
||||
static const uint32_t MAX_LENGTH = JSString::MAX_LENGTH;
|
||||
@ -276,19 +298,18 @@ class alignas(alignof(void*)) ParserAtomEntry {
|
||||
template <typename CharT>
|
||||
bool equalsSeq(HashNumber hash, InflatedChar16Sequence<CharT> seq) const;
|
||||
|
||||
void setAtom(JSAtom* atom) const {
|
||||
MOZ_ASSERT(atom != nullptr);
|
||||
if (jsatom_ != nullptr) {
|
||||
MOZ_ASSERT(jsatom_ == atom);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(equalsJSAtom(atom));
|
||||
jsatom_ = atom;
|
||||
void setAtomIndex(AtomIndex index) const {
|
||||
atomIndex_.construct<AtomIndex>(index);
|
||||
}
|
||||
|
||||
void setWellKnownAtomId(WellKnownAtomId kind) const {
|
||||
atomIndex_.construct<WellKnownAtomId>(kind);
|
||||
}
|
||||
|
||||
// Convert this entry to a js-atom. The first time this method is called
|
||||
// the entry will cache the JSAtom pointer to return later.
|
||||
JS::Result<JSAtom*, OOM&> toJSAtom(JSContext* cx) const;
|
||||
JS::Result<JSAtom*, OOM&> toJSAtom(JSContext* cx,
|
||||
CompilationInfo& compilationInfo) const;
|
||||
|
||||
// Convert this entry to a number.
|
||||
bool toNumber(JSContext* cx, double* result) const;
|
||||
@ -368,7 +389,7 @@ class WellKnownParserAtoms {
|
||||
EntrySet entrySet_;
|
||||
|
||||
bool initSingle(JSContext* cx, const ParserName** name, const char* str,
|
||||
JSAtom* jsatom);
|
||||
WellKnownAtomId kind);
|
||||
|
||||
public:
|
||||
explicit WellKnownParserAtoms(JSContext* cx) : entrySet_(cx) {}
|
||||
@ -459,7 +480,8 @@ class ParserAtomsTable {
|
||||
JS::Result<const ParserAtom*, OOM&> internUtf8(
|
||||
JSContext* cx, const mozilla::Utf8Unit* utf8Ptr, uint32_t length);
|
||||
|
||||
JS::Result<const ParserAtom*, OOM&> internJSAtom(JSContext* cx, JSAtom* atom);
|
||||
JS::Result<const ParserAtom*, OOM&> internJSAtom(
|
||||
JSContext* cx, CompilationInfo& compilationInfo, JSAtom* atom);
|
||||
|
||||
JS::Result<const ParserAtom*, OOM&> concatAtoms(
|
||||
JSContext* cx, mozilla::Range<const ParserAtom*> atoms);
|
||||
|
@ -465,8 +465,6 @@ JS_PUBLIC_API bool JS::InitSelfHostedCode(JSContext* cx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialization of well-known ParserAtoms must happen AFTER
|
||||
// initialization of the coresponding JSAtoms.
|
||||
if (!rt->initializeParserAtoms(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -150,8 +150,9 @@ Shape* js::CreateEnvironmentShape(JSContext* cx, BindingIter& bi,
|
||||
}
|
||||
|
||||
Shape* js::CreateEnvironmentShape(
|
||||
JSContext* cx, AbstractBindingIter<const frontend::ParserAtom>& bi,
|
||||
const JSClass* cls, uint32_t numSlots, uint32_t baseShapeFlags) {
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
AbstractBindingIter<const frontend::ParserAtom>& bi, const JSClass* cls,
|
||||
uint32_t numSlots, uint32_t baseShapeFlags) {
|
||||
RootedShape shape(cx,
|
||||
EmptyEnvironmentShape(cx, cls, numSlots, baseShapeFlags));
|
||||
if (!shape) {
|
||||
@ -163,7 +164,7 @@ Shape* js::CreateEnvironmentShape(
|
||||
for (; bi; bi++) {
|
||||
BindingLocation loc = bi.location();
|
||||
if (loc.kind() == BindingLocation::Kind::Environment) {
|
||||
auto mbJSAtom = bi.name()->toJSAtom(cx);
|
||||
auto mbJSAtom = bi.name()->toJSAtom(cx, compilationInfo);
|
||||
if (mbJSAtom.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -295,7 +296,8 @@ static UniquePtr<AbstractScopeData<ConcreteScope, AtomT>> NewEmptyScopeData(
|
||||
|
||||
template <typename ConcreteScope>
|
||||
static UniquePtr<typename ConcreteScope::Data> LiftParserScopeData(
|
||||
JSContext* cx, ParserScopeData<ConcreteScope>* data) {
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
ParserScopeData<ConcreteScope>* data) {
|
||||
using ConcreteData = typename ConcreteScope::Data;
|
||||
|
||||
// Convert all scope ParserAtoms to rooted JSAtoms.
|
||||
@ -309,7 +311,7 @@ static UniquePtr<typename ConcreteScope::Data> LiftParserScopeData(
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
JSAtom* jsatom = nullptr;
|
||||
if (names[i].name()) {
|
||||
jsatom = names[i].name()->toJSAtom(cx).unwrapOr(nullptr);
|
||||
jsatom = names[i].name()->toJSAtom(cx, compilationInfo).unwrapOr(nullptr);
|
||||
if (jsatom == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2168,7 +2170,8 @@ bool ScopeStencil::createForWithScope(
|
||||
template <typename SpecificScopeT>
|
||||
UniquePtr<typename SpecificScopeT::Data> ScopeStencil::createSpecificScopeData(
|
||||
JSContext* cx, CompilationInfo& compilationInfo) {
|
||||
return LiftParserScopeData<SpecificScopeT>(cx, &data<SpecificScopeT>());
|
||||
return LiftParserScopeData<SpecificScopeT>(cx, compilationInfo,
|
||||
&data<SpecificScopeT>());
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -2176,8 +2179,8 @@ UniquePtr<FunctionScope::Data>
|
||||
ScopeStencil::createSpecificScopeData<FunctionScope>(
|
||||
JSContext* cx, CompilationInfo& compilationInfo) {
|
||||
// Allocate a new vm function-scope.
|
||||
UniquePtr<FunctionScope::Data> data =
|
||||
LiftParserScopeData<FunctionScope>(cx, &this->data<FunctionScope>());
|
||||
UniquePtr<FunctionScope::Data> data = LiftParserScopeData<FunctionScope>(
|
||||
cx, compilationInfo, &this->data<FunctionScope>());
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2192,8 +2195,8 @@ template <>
|
||||
UniquePtr<ModuleScope::Data> ScopeStencil::createSpecificScopeData<ModuleScope>(
|
||||
JSContext* cx, CompilationInfo& compilationInfo) {
|
||||
// Allocate a new vm module-scope.
|
||||
UniquePtr<ModuleScope::Data> data =
|
||||
LiftParserScopeData<ModuleScope>(cx, &this->data<ModuleScope>());
|
||||
UniquePtr<ModuleScope::Data> data = LiftParserScopeData<ModuleScope>(
|
||||
cx, compilationInfo, &this->data<ModuleScope>());
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1633,8 +1633,9 @@ Shape* CreateEnvironmentShape(JSContext* cx, BindingIter& bi,
|
||||
uint32_t baseShapeFlags);
|
||||
|
||||
Shape* CreateEnvironmentShape(
|
||||
JSContext* cx, AbstractBindingIter<const frontend::ParserAtom>& bi,
|
||||
const JSClass* cls, uint32_t numSlots, uint32_t baseShapeFlags);
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
AbstractBindingIter<const frontend::ParserAtom>& bi, const JSClass* cls,
|
||||
uint32_t numSlots, uint32_t baseShapeFlags);
|
||||
|
||||
Shape* EmptyEnvironmentShape(JSContext* cx, const JSClass* cls,
|
||||
uint32_t numSlots, uint32_t baseShapeFlags);
|
||||
|
Loading…
Reference in New Issue
Block a user