зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1660798) for causing memory leaks. CLOSED TREE
Backed out changeset 846f88debca6 (bug 1660798) Backed out changeset 12d099efac67 (bug 1660798)
This commit is contained in:
Родитель
7b214fd81a
Коммит
f66ec87fd8
|
@ -78,6 +78,12 @@ set_define('JS_64BIT', depends(target)(lambda t: t.bitness == 64 or None))
|
|||
set_define('JS_PUNBOX64', depends(target)(lambda t: t.bitness == 64 or None))
|
||||
set_define('JS_NUNBOX32', depends(target)(lambda t: t.bitness == 32 or None))
|
||||
|
||||
# Bits of Stencil-related parser-atoms work are being landed before
|
||||
# being enabled. This define controls that code, and will be removed,
|
||||
# along with guard code in ParserAtoms.cpp, when the final transition
|
||||
# to parser atoms lands.
|
||||
set_define('JS_PARSER_ATOMS', None)
|
||||
|
||||
|
||||
# SpiderMonkey as a shared library, and how its symbols are exported
|
||||
# ==================================================================
|
||||
|
|
|
@ -1234,7 +1234,7 @@ bool ModuleBuilder::buildTables(frontend::StencilModuleMetadata& metadata) {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
if (importEntry->importName == cx_->parserNames().star) {
|
||||
if (importEntry->importName == cx_->names().star) {
|
||||
if (!metadata.localExportEntries.append(exp)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1247,7 +1247,7 @@ bool ModuleBuilder::buildTables(frontend::StencilModuleMetadata& metadata) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (exp.importName == cx_->parserNames().star && !exp.exportName) {
|
||||
} else if (exp.importName == cx_->names().star && !exp.exportName) {
|
||||
if (!metadata.starExportEntries.append(exp)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1273,8 +1273,7 @@ enum class ModuleArrayType {
|
|||
};
|
||||
|
||||
static ArrayObject* ModuleBuilderInitArray(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
ModuleArrayType arrayType,
|
||||
JSContext* cx, ModuleArrayType arrayType,
|
||||
const frontend::StencilModuleMetadata::EntryVector& vector) {
|
||||
RootedArrayObject resultArray(
|
||||
cx, NewDenseFullyAllocatedArray(cx, vector.length()));
|
||||
|
@ -1292,34 +1291,10 @@ static ArrayObject* ModuleBuilderInitArray(
|
|||
|
||||
for (uint32_t i = 0; i < vector.length(); ++i) {
|
||||
const frontend::StencilModuleEntry& entry = vector[i];
|
||||
|
||||
if (entry.specifier) {
|
||||
specifier = compilationInfo.liftParserAtomToJSAtom(entry.specifier);
|
||||
if (!specifier) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.localName) {
|
||||
localName = compilationInfo.liftParserAtomToJSAtom(entry.localName);
|
||||
if (!localName) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.importName) {
|
||||
importName = compilationInfo.liftParserAtomToJSAtom(entry.importName);
|
||||
if (!importName) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.exportName) {
|
||||
exportName = compilationInfo.liftParserAtomToJSAtom(entry.exportName);
|
||||
if (!exportName) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
specifier = entry.specifier;
|
||||
localName = entry.localName;
|
||||
importName = entry.importName;
|
||||
exportName = entry.exportName;
|
||||
|
||||
switch (arrayType) {
|
||||
case ModuleArrayType::ImportEntryObject:
|
||||
|
@ -1352,43 +1327,37 @@ static ArrayObject* ModuleBuilderInitArray(
|
|||
|
||||
// Use StencilModuleMetadata data to fill in ModuleObject
|
||||
bool frontend::StencilModuleMetadata::initModule(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
JS::Handle<ModuleObject*> module) {
|
||||
JSContext* cx, JS::Handle<ModuleObject*> module) {
|
||||
RootedArrayObject requestedModulesObject(
|
||||
cx, ModuleBuilderInitArray(cx, compilationInfo,
|
||||
ModuleArrayType::RequestedModuleObject,
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::RequestedModuleObject,
|
||||
requestedModules));
|
||||
if (!requestedModulesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject importEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, compilationInfo,
|
||||
ModuleArrayType::ImportEntryObject,
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ImportEntryObject,
|
||||
importEntries));
|
||||
if (!importEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject localExportEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, compilationInfo,
|
||||
ModuleArrayType::ExportEntryObject,
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ExportEntryObject,
|
||||
localExportEntries));
|
||||
if (!localExportEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject indirectExportEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, compilationInfo,
|
||||
ModuleArrayType::ExportEntryObject,
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ExportEntryObject,
|
||||
indirectExportEntries));
|
||||
if (!indirectExportEntriesObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject starExportEntriesObject(
|
||||
cx, ModuleBuilderInitArray(cx, compilationInfo,
|
||||
ModuleArrayType::ExportEntryObject,
|
||||
cx, ModuleBuilderInitArray(cx, ModuleArrayType::ExportEntryObject,
|
||||
starExportEntries));
|
||||
if (!starExportEntriesObject) {
|
||||
return false;
|
||||
|
@ -1415,20 +1384,23 @@ bool ModuleBuilder::processImport(frontend::BinaryNode* importNode) {
|
|||
NameNode* moduleSpec = &importNode->right()->as<NameNode>();
|
||||
MOZ_ASSERT(moduleSpec->isKind(ParseNodeKind::StringExpr));
|
||||
|
||||
const ParserAtom* module = moduleSpec->atom();
|
||||
RootedAtom module(cx_, moduleSpec->atom());
|
||||
if (!maybeAppendRequestedModule(module, moduleSpec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedAtom importName(cx_);
|
||||
RootedAtom localName(cx_);
|
||||
for (ParseNode* item : specList->contents()) {
|
||||
BinaryNode* spec = &item->as<BinaryNode>();
|
||||
MOZ_ASSERT(spec->isKind(ParseNodeKind::ImportSpec));
|
||||
|
||||
NameNode* importNameNode = &spec->left()->as<NameNode>();
|
||||
|
||||
NameNode* localNameNode = &spec->right()->as<NameNode>();
|
||||
|
||||
const ParserAtom* importName = importNameNode->atom();
|
||||
const ParserAtom* localName = localNameNode->atom();
|
||||
importName = importNameNode->atom();
|
||||
localName = localNameNode->atom();
|
||||
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
|
@ -1457,24 +1429,24 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
|
|||
|
||||
if (isDefault && exportNode->as<BinaryNode>().right()) {
|
||||
// This is an export default containing an expression.
|
||||
const ParserAtom* localName = cx_->parserNames().default_;
|
||||
const ParserAtom* exportName = cx_->parserNames().default_;
|
||||
HandlePropertyName localName = cx_->names().default_;
|
||||
HandlePropertyName exportName = cx_->names().default_;
|
||||
return appendExportEntry(exportName, localName);
|
||||
}
|
||||
|
||||
switch (kid->getKind()) {
|
||||
case ParseNodeKind::ExportSpecList: {
|
||||
MOZ_ASSERT(!isDefault);
|
||||
RootedAtom localName(cx_);
|
||||
RootedAtom exportName(cx_);
|
||||
for (ParseNode* item : kid->as<ListNode>().contents()) {
|
||||
BinaryNode* spec = &item->as<BinaryNode>();
|
||||
MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportSpec));
|
||||
|
||||
NameNode* localNameNode = &spec->left()->as<NameNode>();
|
||||
NameNode* exportNameNode = &spec->right()->as<NameNode>();
|
||||
|
||||
const ParserAtom* localName = localNameNode->atom();
|
||||
const ParserAtom* exportName = exportNameNode->atom();
|
||||
|
||||
localName = localNameNode->atom();
|
||||
exportName = exportNameNode->atom();
|
||||
if (!appendExportEntry(exportName, localName, spec)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1485,10 +1457,9 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
|
|||
case ParseNodeKind::ClassDecl: {
|
||||
const ClassNode& cls = kid->as<ClassNode>();
|
||||
MOZ_ASSERT(cls.names());
|
||||
const frontend::ParserAtom* localName =
|
||||
cls.names()->innerBinding()->atom();
|
||||
const frontend::ParserAtom* exportName =
|
||||
isDefault ? cx_->parserNames().default_ : localName;
|
||||
RootedAtom localName(cx_, cls.names()->innerBinding()->atom());
|
||||
RootedAtom exportName(
|
||||
cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
if (!appendExportEntry(exportName, localName)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1498,6 +1469,8 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
|
|||
case ParseNodeKind::VarStmt:
|
||||
case ParseNodeKind::ConstDecl:
|
||||
case ParseNodeKind::LetDecl: {
|
||||
RootedAtom localName(cx_);
|
||||
RootedAtom exportName(cx_);
|
||||
for (ParseNode* binding : kid->as<ListNode>().contents()) {
|
||||
if (binding->isKind(ParseNodeKind::AssignExpr)) {
|
||||
binding = binding->as<AssignmentNode>().left();
|
||||
|
@ -1506,10 +1479,8 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
|
|||
}
|
||||
|
||||
if (binding->isKind(ParseNodeKind::Name)) {
|
||||
const frontend::ParserAtom* localName =
|
||||
binding->as<NameNode>().atom();
|
||||
const frontend::ParserAtom* exportName =
|
||||
isDefault ? cx_->parserNames().default_ : localName;
|
||||
localName = binding->as<NameNode>().atom();
|
||||
exportName = isDefault ? cx_->names().default_ : localName.get();
|
||||
if (!appendExportEntry(exportName, localName)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1530,9 +1501,10 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
|
|||
case ParseNodeKind::Function: {
|
||||
FunctionBox* box = kid->as<FunctionNode>().funbox();
|
||||
MOZ_ASSERT(!box->isArrow());
|
||||
const frontend::ParserAtom* localName = box->explicitName();
|
||||
const frontend::ParserAtom* exportName =
|
||||
isDefault ? cx_->parserNames().default_ : localName;
|
||||
RootedAtom localName(cx_, box->explicitName());
|
||||
RootedAtom exportName(
|
||||
cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
MOZ_ASSERT_IF(isDefault, localName);
|
||||
if (!appendExportEntry(exportName, localName)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1550,7 +1522,7 @@ bool ModuleBuilder::processExportBinding(frontend::ParseNode* binding) {
|
|||
using namespace js::frontend;
|
||||
|
||||
if (binding->isKind(ParseNodeKind::Name)) {
|
||||
const frontend::ParserAtom* name = binding->as<NameNode>().atom();
|
||||
RootedAtom name(cx_, binding->as<NameNode>().atom());
|
||||
return appendExportEntry(name, name);
|
||||
}
|
||||
|
||||
|
@ -1631,28 +1603,27 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) {
|
|||
NameNode* moduleSpec = &exportNode->right()->as<NameNode>();
|
||||
MOZ_ASSERT(moduleSpec->isKind(ParseNodeKind::StringExpr));
|
||||
|
||||
const frontend::ParserAtom* module = moduleSpec->atom();
|
||||
|
||||
RootedAtom module(cx_, moduleSpec->atom());
|
||||
if (!maybeAppendRequestedModule(module, moduleSpec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedAtom bindingName(cx_);
|
||||
RootedAtom exportName(cx_);
|
||||
for (ParseNode* spec : specList->contents()) {
|
||||
if (spec->isKind(ParseNodeKind::ExportSpec)) {
|
||||
NameNode* localNameNode = &spec->as<BinaryNode>().left()->as<NameNode>();
|
||||
NameNode* exportNameNode =
|
||||
&spec->as<BinaryNode>().right()->as<NameNode>();
|
||||
|
||||
const frontend::ParserAtom* bindingName = localNameNode->atom();
|
||||
const frontend::ParserAtom* exportName = exportNameNode->atom();
|
||||
|
||||
bindingName = localNameNode->atom();
|
||||
exportName = exportNameNode->atom();
|
||||
if (!appendExportFromEntry(exportName, module, bindingName,
|
||||
localNameNode)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportBatchSpecStmt));
|
||||
const frontend::ParserAtom* exportName = cx_->parserNames().star;
|
||||
exportName = cx_->names().star;
|
||||
if (!appendExportFromEntry(nullptr, module, exportName, spec)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1663,7 +1634,7 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) {
|
|||
}
|
||||
|
||||
frontend::StencilModuleEntry* ModuleBuilder::importEntryFor(
|
||||
const frontend::ParserAtom* localName) const {
|
||||
JSAtom* localName) const {
|
||||
MOZ_ASSERT(localName);
|
||||
auto ptr = importEntries_.lookup(localName);
|
||||
if (!ptr) {
|
||||
|
@ -1673,13 +1644,13 @@ frontend::StencilModuleEntry* ModuleBuilder::importEntryFor(
|
|||
return &ptr->value();
|
||||
}
|
||||
|
||||
bool ModuleBuilder::hasExportedName(const frontend::ParserAtom* name) const {
|
||||
bool ModuleBuilder::hasExportedName(JSAtom* name) const {
|
||||
MOZ_ASSERT(name);
|
||||
return exportNames_.has(name);
|
||||
}
|
||||
|
||||
bool ModuleBuilder::appendExportEntry(const frontend::ParserAtom* exportName,
|
||||
const frontend::ParserAtom* localName,
|
||||
bool ModuleBuilder::appendExportEntry(HandleAtom exportName,
|
||||
HandleAtom localName,
|
||||
frontend::ParseNode* node) {
|
||||
uint32_t line = 0;
|
||||
uint32_t column = 0;
|
||||
|
@ -1702,10 +1673,10 @@ bool ModuleBuilder::appendExportEntry(const frontend::ParserAtom* exportName,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ModuleBuilder::appendExportFromEntry(
|
||||
const frontend::ParserAtom* exportName,
|
||||
const frontend::ParserAtom* moduleRequest,
|
||||
const frontend::ParserAtom* importName, frontend::ParseNode* node) {
|
||||
bool ModuleBuilder::appendExportFromEntry(HandleAtom exportName,
|
||||
HandleAtom moduleRequest,
|
||||
HandleAtom importName,
|
||||
frontend::ParseNode* node) {
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
eitherParser_.computeLineAndColumn(node->pn_pos.begin, &line, &column);
|
||||
|
@ -1719,8 +1690,8 @@ bool ModuleBuilder::appendExportFromEntry(
|
|||
return !exportName || exportNames_.put(exportName);
|
||||
}
|
||||
|
||||
bool ModuleBuilder::maybeAppendRequestedModule(
|
||||
const frontend::ParserAtom* specifier, frontend::ParseNode* node) {
|
||||
bool ModuleBuilder::maybeAppendRequestedModule(HandleAtom specifier,
|
||||
frontend::ParseNode* node) {
|
||||
if (requestedModuleSpecifiers_.has(specifier)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2473,13 +2473,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
|
|||
case ParseNodeKind::ContinueStmt: {
|
||||
LoopControlStatement* node = &pn->as<LoopControlStatement>();
|
||||
RootedValue label(cx);
|
||||
RootedAtom pnAtom(cx);
|
||||
if (node->label()) {
|
||||
pnAtom.set(parser->liftParserAtomToJSAtom(node->label()));
|
||||
if (!pnAtom) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
RootedAtom pnAtom(cx, node->label());
|
||||
return optIdentifier(pnAtom, nullptr, &label) &&
|
||||
(node->isKind(ParseNodeKind::BreakStmt)
|
||||
? builder.breakStatement(label, &node->pn_pos, dst)
|
||||
|
@ -2492,10 +2486,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
|
|||
MOZ_ASSERT(labelNode->pn_pos.encloses(stmtNode->pn_pos));
|
||||
|
||||
RootedValue label(cx), stmt(cx);
|
||||
RootedAtom pnAtom(cx, parser->liftParserAtomToJSAtom(labelNode->label()));
|
||||
if (!pnAtom.get()) {
|
||||
return false;
|
||||
}
|
||||
RootedAtom pnAtom(cx, labelNode->label());
|
||||
return identifier(pnAtom, nullptr, &label) &&
|
||||
statement(stmtNode, &stmt) &&
|
||||
builder.labeledStatement(label, stmt, &labelNode->pn_pos, dst);
|
||||
|
@ -2928,10 +2919,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
|
|||
|
||||
RootedValue expr(cx);
|
||||
RootedValue propname(cx);
|
||||
RootedAtom pnAtom(cx, parser->liftParserAtomToJSAtom(prop->key().atom()));
|
||||
if (!pnAtom.get()) {
|
||||
return false;
|
||||
}
|
||||
RootedAtom pnAtom(cx, prop->key().atom());
|
||||
|
||||
if (isSuper) {
|
||||
if (!builder.super(&prop->expression().pn_pos, &expr)) {
|
||||
|
@ -2989,11 +2977,8 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
|
|||
NameNode* rawItem = &item->as<NameNode>();
|
||||
MOZ_ASSERT(callSiteObj->pn_pos.encloses(rawItem->pn_pos));
|
||||
|
||||
JSAtom* exprAtom = parser->liftParserAtomToJSAtom(rawItem->atom());
|
||||
if (!exprAtom) {
|
||||
return false;
|
||||
}
|
||||
RootedValue expr(cx, StringValue(exprAtom));
|
||||
RootedValue expr(cx);
|
||||
expr.setString(rawItem->atom());
|
||||
raw.infallibleAppend(expr);
|
||||
}
|
||||
|
||||
|
@ -3011,12 +2996,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
|
|||
expr.setUndefined();
|
||||
} else {
|
||||
MOZ_ASSERT(cookedItem->isKind(ParseNodeKind::TemplateStringExpr));
|
||||
JSAtom* exprAtom =
|
||||
parser->liftParserAtomToJSAtom(cookedItem->as<NameNode>().atom());
|
||||
if (!exprAtom) {
|
||||
return false;
|
||||
}
|
||||
expr.setString(exprAtom);
|
||||
expr.setString(cookedItem->as<NameNode>().atom());
|
||||
}
|
||||
cooked.infallibleAppend(expr);
|
||||
}
|
||||
|
@ -3270,15 +3250,9 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
|
|||
RootedValue val(cx);
|
||||
switch (pn->getKind()) {
|
||||
case ParseNodeKind::TemplateStringExpr:
|
||||
case ParseNodeKind::StringExpr: {
|
||||
JSAtom* exprAtom =
|
||||
parser->liftParserAtomToJSAtom(pn->as<NameNode>().atom());
|
||||
if (!exprAtom) {
|
||||
return false;
|
||||
}
|
||||
val.setString(exprAtom);
|
||||
case ParseNodeKind::StringExpr:
|
||||
val.setString(pn->as<NameNode>().atom());
|
||||
break;
|
||||
}
|
||||
|
||||
case ParseNodeKind::RegExpExpr: {
|
||||
RegExpObject* re =
|
||||
|
@ -3441,10 +3415,7 @@ bool ASTSerializer::identifier(HandleAtom atom, TokenPos* pos,
|
|||
bool ASTSerializer::identifier(NameNode* id, MutableHandleValue dst) {
|
||||
LOCAL_ASSERT(id->atom());
|
||||
|
||||
RootedAtom pnAtom(cx, parser->liftParserAtomToJSAtom(id->atom()));
|
||||
if (!pnAtom.get()) {
|
||||
return false;
|
||||
}
|
||||
RootedAtom pnAtom(cx, id->atom());
|
||||
return identifier(pnAtom, &id->pn_pos, dst);
|
||||
}
|
||||
|
||||
|
@ -3459,13 +3430,7 @@ bool ASTSerializer::function(FunctionNode* funNode, ASTType type,
|
|||
bool isExpression = funbox->hasExprBody();
|
||||
|
||||
RootedValue id(cx);
|
||||
RootedAtom funcAtom(cx);
|
||||
if (funbox->explicitName()) {
|
||||
funcAtom.set(parser->liftParserAtomToJSAtom(funbox->explicitName()));
|
||||
if (!funcAtom) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
RootedAtom funcAtom(cx, funbox->explicitName());
|
||||
if (!optIdentifier(funcAtom, nullptr, &id)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "frontend/ErrorReporter.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/ParserAtom.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
|
|
@ -107,7 +107,6 @@ namespace frontend {
|
|||
class ErrorReporter;
|
||||
class FunctionBox;
|
||||
class ParseNode;
|
||||
class ParserAtom;
|
||||
|
||||
// Compile a module of the given source using the given options.
|
||||
ModuleObject* CompileModule(JSContext* cx,
|
||||
|
@ -175,10 +174,8 @@ MOZ_MUST_USE JSFunction* CompileStandaloneAsyncGenerator(
|
|||
* Defined in TokenStream.cpp.
|
||||
*/
|
||||
bool IsIdentifier(JSLinearString* str);
|
||||
bool IsIdentifier(const ParserAtom* atom);
|
||||
|
||||
bool IsIdentifierNameOrPrivateName(JSLinearString* str);
|
||||
bool IsIdentifierNameOrPrivateName(const ParserAtom* atom);
|
||||
|
||||
/*
|
||||
* As above, but taking chars + length.
|
||||
|
@ -190,7 +187,6 @@ bool IsIdentifierNameOrPrivateName(const Latin1Char* chars, size_t length);
|
|||
bool IsIdentifierNameOrPrivateName(const char16_t* chars, size_t length);
|
||||
|
||||
/* True if str is a keyword. Defined in TokenStream.cpp. */
|
||||
bool IsKeyword(const ParserAtom* atom);
|
||||
bool IsKeyword(JSLinearString* str);
|
||||
|
||||
class MOZ_STACK_CLASS AutoFrontendTraceLog {
|
||||
|
|
|
@ -29,10 +29,10 @@ bool BreakableControl::patchBreaks(BytecodeEmitter* bce) {
|
|||
return bce->emitJumpTargetAndPatch(breaks);
|
||||
}
|
||||
|
||||
LabelControl::LabelControl(BytecodeEmitter* bce, const ParserAtom* label,
|
||||
LabelControl::LabelControl(BytecodeEmitter* bce, JSAtom* label,
|
||||
BytecodeOffset startOffset)
|
||||
: BreakableControl(bce, StatementKind::Label),
|
||||
label_(label),
|
||||
label_(bce->cx, label),
|
||||
startOffset_(startOffset) {}
|
||||
|
||||
LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
#include "ds/Nestable.h" // Nestable
|
||||
#include "frontend/BytecodeSection.h" // BytecodeOffset
|
||||
#include "frontend/JumpList.h" // JumpList, JumpTarget
|
||||
#include "frontend/ParserAtom.h" // ParserAtom
|
||||
#include "frontend/SharedContext.h" // StatementKind, StatementKindIsLoop, StatementKindIsUnlabeledBreakTarget
|
||||
#include "frontend/TDZCheckCache.h" // TDZCheckCache
|
||||
#include "gc/Rooting.h" // RootedAtom, HandleAtom
|
||||
#include "vm/StencilEnums.h" // TryNoteKind
|
||||
#include "vm/StringType.h" // JSAtom
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
@ -70,16 +71,15 @@ inline bool NestableControl::is<BreakableControl>() const {
|
|||
}
|
||||
|
||||
class LabelControl : public BreakableControl {
|
||||
const ParserAtom* label_;
|
||||
RootedAtom label_;
|
||||
|
||||
// The code offset when this was pushed. Used for effectfulness checking.
|
||||
BytecodeOffset startOffset_;
|
||||
|
||||
public:
|
||||
LabelControl(BytecodeEmitter* bce, const ParserAtom* label,
|
||||
BytecodeOffset startOffset);
|
||||
LabelControl(BytecodeEmitter* bce, JSAtom* label, BytecodeOffset startOffset);
|
||||
|
||||
const ParserAtom* label() const { return label_; }
|
||||
HandleAtom label() const { return label_; }
|
||||
|
||||
BytecodeOffset startOffset() const { return startOffset_; }
|
||||
};
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "frontend/OptionalEmitter.h" // OptionalEmitter
|
||||
#include "frontend/ParseNode.h" // ParseNodeKind, ParseNode and subclasses
|
||||
#include "frontend/Parser.h" // Parser
|
||||
#include "frontend/ParserAtom.h" // ParserAtomsTable
|
||||
#include "frontend/PropOpEmitter.h" // PropOpEmitter
|
||||
#include "frontend/SourceNotes.h" // SrcNote, SrcNoteType, SrcNoteWriter
|
||||
#include "frontend/SwitchEmitter.h" // SwitchEmitter
|
||||
|
@ -173,17 +172,17 @@ T* BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const {
|
|||
return NestableControl::findNearest<T>(innermostNestableControl, predicate);
|
||||
}
|
||||
|
||||
NameLocation BytecodeEmitter::lookupName(const ParserAtom* name) {
|
||||
NameLocation BytecodeEmitter::lookupName(JSAtom* name) {
|
||||
return innermostEmitterScope()->lookup(this, name);
|
||||
}
|
||||
|
||||
Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInScope(
|
||||
const ParserAtom* name, EmitterScope* target) {
|
||||
JSAtom* name, EmitterScope* target) {
|
||||
return innermostEmitterScope()->locationBoundInScope(name, target);
|
||||
}
|
||||
|
||||
Maybe<NameLocation> BytecodeEmitter::locationOfNameBoundInFunctionScope(
|
||||
const ParserAtom* name, EmitterScope* source) {
|
||||
JSAtom* name, EmitterScope* source) {
|
||||
EmitterScope* funScope = source;
|
||||
while (!funScope->scope(this).is<FunctionScope>()) {
|
||||
funScope = funScope->enclosingInFrame();
|
||||
|
@ -904,7 +903,7 @@ bool BytecodeEmitter::emitGCIndexOp(JSOp op, GCThingIndex index) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitAtomOp(JSOp op, const ParserAtom* atom,
|
||||
bool BytecodeEmitter::emitAtomOp(JSOp op, JSAtom* atom,
|
||||
ShouldInstrument shouldInstrument) {
|
||||
MOZ_ASSERT(atom);
|
||||
|
||||
|
@ -1657,9 +1656,8 @@ bool BytecodeEmitter::iteratorResultShape(GCThingIndex* shape) {
|
|||
|
||||
data.writer().beginObject(flags);
|
||||
|
||||
using WellKnownName = js::frontend::WellKnownParserAtoms;
|
||||
for (auto name : {&WellKnownName::value, &WellKnownName::done}) {
|
||||
const ParserAtom* propName = cx->parserNames().*name;
|
||||
for (auto name : {&JSAtomState::value, &JSAtomState::done}) {
|
||||
HandlePropertyName propName = cx->parserNames().*name;
|
||||
|
||||
uint32_t propNameIndex = 0;
|
||||
if (!data.addAtom(propName, &propNameIndex)) {
|
||||
|
@ -1696,7 +1694,7 @@ bool BytecodeEmitter::emitFinishIteratorResult(bool done) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitGetNameAtLocation(const ParserAtom* name,
|
||||
bool BytecodeEmitter::emitGetNameAtLocation(Handle<JSAtom*> name,
|
||||
const NameLocation& loc) {
|
||||
NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
|
||||
if (!noe.emitGet()) {
|
||||
|
@ -1709,7 +1707,7 @@ bool BytecodeEmitter::emitGetNameAtLocation(const ParserAtom* name,
|
|||
bool BytecodeEmitter::emitGetName(NameNode* name) {
|
||||
MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
|
||||
|
||||
const ParserAtom* nameAtom = name->name();
|
||||
RootedAtom nameAtom(cx, name->name());
|
||||
return emitGetName(nameAtom);
|
||||
}
|
||||
|
||||
|
@ -1718,7 +1716,9 @@ bool BytecodeEmitter::emitGetPrivateName(NameNode* name) {
|
|||
return emitGetPrivateName(name->name());
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitGetPrivateName(const ParserAtom* nameAtom) {
|
||||
bool BytecodeEmitter::emitGetPrivateName(JSAtom* name) {
|
||||
RootedAtom nameAtom(cx, name);
|
||||
|
||||
// The parser ensures the private name is present on the environment chain.
|
||||
NameLocation location = lookupName(nameAtom);
|
||||
MOZ_ASSERT(location.kind() == NameLocation::Kind::FrameSlot ||
|
||||
|
@ -1728,7 +1728,7 @@ bool BytecodeEmitter::emitGetPrivateName(const ParserAtom* nameAtom) {
|
|||
return emitGetNameAtLocation(nameAtom, location);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitTDZCheckIfNeeded(const ParserAtom* name,
|
||||
bool BytecodeEmitter::emitTDZCheckIfNeeded(HandleAtom name,
|
||||
const NameLocation& loc,
|
||||
ValueIsOnStack isOnStack) {
|
||||
// Dynamic accesses have TDZ checks built into their VM code and should
|
||||
|
@ -1876,7 +1876,7 @@ bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec) {
|
|||
|
||||
ParseNodeKind kind = incDec->getKind();
|
||||
NameNode* name = &incDec->kid()->as<NameNode>();
|
||||
const ParserAtom* nameAtom = name->atom();
|
||||
RootedAtom nameAtom(cx, name->atom());
|
||||
NameOpEmitter noe(this, nameAtom,
|
||||
kind == ParseNodeKind::PostIncrementExpr
|
||||
? NameOpEmitter::Kind::PostIncrement
|
||||
|
@ -2306,7 +2306,7 @@ bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
|
|||
MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis));
|
||||
MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name));
|
||||
|
||||
const ParserAtom* name = setThisNode->left()->as<NameNode>().name();
|
||||
RootedAtom name(cx, setThisNode->left()->as<NameNode>().name());
|
||||
|
||||
// The 'this' binding is not lexical, but due to super() semantics this
|
||||
// initialization needs to be treated as a lexical one.
|
||||
|
@ -2473,12 +2473,12 @@ bool BytecodeEmitter::emitScript(ParseNode* body) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!NameFunctions(cx, compilationInfo, body)) {
|
||||
if (!NameFunctions(cx, body)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a Stencil and convert it into a JSScript.
|
||||
return intoScriptStencil(&compilationInfo.topLevel.get());
|
||||
return intoScriptStencil(compilationInfo.topLevel.address());
|
||||
}
|
||||
|
||||
js::UniquePtr<ImmutableScriptData> BytecodeEmitter::createImmutableScriptData(
|
||||
|
@ -2552,7 +2552,7 @@ bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode,
|
|||
}
|
||||
|
||||
if (isTopLevel == TopLevelFunction::Yes) {
|
||||
if (!NameFunctions(cx, compilationInfo, funNode)) {
|
||||
if (!NameFunctions(cx, funNode)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2691,7 +2691,7 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
|
|||
} else {
|
||||
switch (target->getKind()) {
|
||||
case ParseNodeKind::Name: {
|
||||
const ParserAtom* name = target->as<NameNode>().name();
|
||||
RootedAtom name(cx, target->as<NameNode>().name());
|
||||
NameLocation loc = lookupName(name);
|
||||
NameOpEmitter::Kind kind;
|
||||
switch (flav) {
|
||||
|
@ -3095,7 +3095,7 @@ bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
|
|||
}
|
||||
|
||||
bool BytecodeEmitter::emitAnonymousFunctionWithName(ParseNode* node,
|
||||
const ParserAtom* name) {
|
||||
HandleAtom name) {
|
||||
MOZ_ASSERT(node->isDirectRHSAnonFunction());
|
||||
|
||||
if (node->is<FunctionNode>()) {
|
||||
|
@ -3139,7 +3139,7 @@ bool BytecodeEmitter::emitAnonymousFunctionWithComputedName(
|
|||
return emitClass(&node->as<ClassNode>(), ClassNameKind::ComputedName);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::setFunName(FunctionBox* funbox, const ParserAtom* name) {
|
||||
bool BytecodeEmitter::setFunName(FunctionBox* funbox, JSAtom* name) {
|
||||
// The inferred name may already be set if this function is an interpreted
|
||||
// lazy function and we OOM'ed after we set the inferred name the first
|
||||
// time.
|
||||
|
@ -3158,7 +3158,7 @@ bool BytecodeEmitter::emitInitializer(ParseNode* initializer,
|
|||
ParseNode* pattern) {
|
||||
if (initializer->isDirectRHSAnonFunction()) {
|
||||
MOZ_ASSERT(!pattern->isInParens());
|
||||
const ParserAtom* name = pattern->as<NameNode>().name();
|
||||
RootedAtom name(cx, pattern->as<NameNode>().name());
|
||||
if (!emitAnonymousFunctionWithName(initializer, name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3836,7 +3836,7 @@ bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
|
|||
}
|
||||
}
|
||||
|
||||
const ParserAtom* pnatom = nullptr;
|
||||
RootedAtom pnatom(cx);
|
||||
for (ParseNode* member : pattern->contents()) {
|
||||
if (member->isKind(ParseNodeKind::Spread)) {
|
||||
MOZ_ASSERT(!member->pn_next, "unexpected trailing element after spread");
|
||||
|
@ -3845,7 +3845,7 @@ bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
|
|||
|
||||
bool isIndex = false;
|
||||
if (member->isKind(ParseNodeKind::MutateProto)) {
|
||||
pnatom = cx->parserNames().proto;
|
||||
pnatom.set(cx->parserNames().proto);
|
||||
} else {
|
||||
ParseNode* key = member->as<BinaryNode>().left();
|
||||
if (key->isKind(ParseNodeKind::NumberExpr)) {
|
||||
|
@ -3860,7 +3860,7 @@ bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
|
|||
isIndex = true;
|
||||
} else if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
|
||||
key->isKind(ParseNodeKind::StringExpr)) {
|
||||
pnatom = key->as<NameNode>().atom();
|
||||
pnatom.set(key->as<NameNode>().atom());
|
||||
} else {
|
||||
// Otherwise this is a computed property name which needs to
|
||||
// be added dynamically.
|
||||
|
@ -3906,7 +3906,7 @@ bool BytecodeEmitter::emitTemplateString(ListNode* templateString) {
|
|||
// Skip empty strings. These are very common: a template string like
|
||||
// `${a}${b}` has three empty strings and without this optimization
|
||||
// we'd emit four JSOp::Add operations instead of just one.
|
||||
if (isString && item->as<NameNode>().atom()->length() == 0) {
|
||||
if (isString && item->as<NameNode>().atom()->empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4006,7 +4006,7 @@ bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
|
|||
return true;
|
||||
}
|
||||
|
||||
const ParserAtom* nameAtom = decl->name();
|
||||
RootedAtom nameAtom(cx, decl->name());
|
||||
NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
|
||||
if (!noe.prepareForRhs()) {
|
||||
// [stack] ENV?
|
||||
|
@ -4049,7 +4049,7 @@ bool BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
|
|||
}
|
||||
|
||||
bool BytecodeEmitter::emitAssignmentRhs(ParseNode* rhs,
|
||||
const ParserAtom* anonFunctionName) {
|
||||
HandleAtom anonFunctionName) {
|
||||
if (rhs->isDirectRHSAnonFunction()) {
|
||||
if (anonFunctionName) {
|
||||
return emitAnonymousFunctionWithName(rhs, anonFunctionName);
|
||||
|
@ -4121,7 +4121,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
|||
lhs->isKind(ParseNodeKind::ElemExpr));
|
||||
|
||||
// |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
|
||||
const ParserAtom* name = nullptr;
|
||||
RootedAtom name(cx);
|
||||
|
||||
Maybe<NameOpEmitter> noe;
|
||||
Maybe<PropOpEmitter> poe;
|
||||
|
@ -4142,7 +4142,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
|||
// implemented via a property or elem assignment (where we are now), and
|
||||
// rhs->isDirectRHSAnonFunction() is set - so we'll assign the name of the
|
||||
// function.
|
||||
const ParserAtom* anonFunctionName = nullptr;
|
||||
RootedAtom anonFunctionName(cx);
|
||||
|
||||
switch (lhs->getKind()) {
|
||||
case ParseNodeKind::Name: {
|
||||
|
@ -4165,7 +4165,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
|
|||
if (!poe->prepareForObj()) {
|
||||
return false;
|
||||
}
|
||||
anonFunctionName = prop->name();
|
||||
anonFunctionName = &prop->name();
|
||||
if (isSuper) {
|
||||
UnaryNode* base = &prop->expression().as<UnaryNode>();
|
||||
if (!emitGetThisForSuperBase(base)) {
|
||||
|
@ -4388,7 +4388,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
|
|||
ParseNode* rhs = node->right();
|
||||
|
||||
// |name| is used within NameOpEmitter, so its lifetime must surpass |noe|.
|
||||
const ParserAtom* name = nullptr;
|
||||
RootedAtom name(cx);
|
||||
|
||||
// Select the appropriate emitter based on the left-hand side.
|
||||
Maybe<NameOpEmitter> noe;
|
||||
|
@ -5338,7 +5338,7 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
|
|||
}
|
||||
|
||||
if (nameNode) {
|
||||
const ParserAtom* nameAtom = nameNode->name();
|
||||
RootedAtom nameAtom(cx, nameNode->name());
|
||||
NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
|
||||
if (!noe.prepareForRhs()) {
|
||||
return false;
|
||||
|
@ -5476,7 +5476,7 @@ bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
|
|||
return false;
|
||||
}
|
||||
|
||||
const ParserAtom* nameAtom = nameNode->name();
|
||||
RootedAtom nameAtom(cx, nameNode->name());
|
||||
NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
|
||||
if (!noe.prepareForRhs()) {
|
||||
return false;
|
||||
|
@ -5853,7 +5853,7 @@ bool BytecodeEmitter::emitWhile(BinaryNode* whileNode) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitBreak(const ParserName* label) {
|
||||
bool BytecodeEmitter::emitBreak(PropertyName* label) {
|
||||
BreakableControl* target;
|
||||
if (label) {
|
||||
// Any statement with the matching label may be the break target.
|
||||
|
@ -5871,7 +5871,7 @@ bool BytecodeEmitter::emitBreak(const ParserName* label) {
|
|||
return emitGoto(target, &target->breaks, GotoKind::Break);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitContinue(const ParserName* label) {
|
||||
bool BytecodeEmitter::emitContinue(PropertyName* label) {
|
||||
LoopControl* target = nullptr;
|
||||
if (label) {
|
||||
// Find the loop statement enclosed by the matching label.
|
||||
|
@ -7054,8 +7054,7 @@ bool BytecodeEmitter::emitDeleteElementInOptChain(PropertyByValueBase* elemExpr,
|
|||
return true;
|
||||
}
|
||||
|
||||
static const char* SelfHostedCallFunctionName(const ParserAtom* name,
|
||||
JSContext* cx) {
|
||||
static const char* SelfHostedCallFunctionName(JSAtom* name, JSContext* cx) {
|
||||
if (name == cx->parserNames().callFunction) {
|
||||
return "callFunction";
|
||||
}
|
||||
|
@ -7176,7 +7175,7 @@ bool BytecodeEmitter::emitSelfHostedResumeGenerator(BinaryNode* callNode) {
|
|||
ParseNode* kindNode = valNode->pn_next;
|
||||
MOZ_ASSERT(kindNode->isKind(ParseNodeKind::StringExpr));
|
||||
GeneratorResumeKind kind =
|
||||
ParserAtomToResumeKind(compilationInfo, kindNode->as<NameNode>().atom());
|
||||
AtomToResumeKind(cx, kindNode->as<NameNode>().atom());
|
||||
MOZ_ASSERT(!kindNode->pn_next);
|
||||
|
||||
if (!emitPushResumeKind(kind)) {
|
||||
|
@ -7347,7 +7346,7 @@ bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
|
|||
return false;
|
||||
}
|
||||
|
||||
const ParserAtom* name = argNode->as<NameNode>().atom();
|
||||
JSAtom* name = argNode->as<NameNode>().atom();
|
||||
|
||||
BuiltinObjectKind kind;
|
||||
if (isConstructor) {
|
||||
|
@ -7440,14 +7439,14 @@ bool BytecodeEmitter::isRestParameter(ParseNode* expr) {
|
|||
expr->as<BinaryNode>().right()->as<ListNode>().head());
|
||||
}
|
||||
|
||||
const ParserAtom* name = expr->as<NameNode>().name();
|
||||
JSAtom* name = expr->as<NameNode>().name();
|
||||
Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
|
||||
if (paramLoc && lookupName(name) == *paramLoc) {
|
||||
ParserFunctionScopeData* bindings = funbox->functionScopeBindings();
|
||||
FunctionScope::Data* bindings = funbox->functionScopeBindings();
|
||||
if (bindings->nonPositionalFormalStart > 0) {
|
||||
// |paramName| can be nullptr when the rest destructuring syntax is
|
||||
// used: `function f(...[]) {}`.
|
||||
const ParserAtom* paramName =
|
||||
JSAtom* paramName =
|
||||
bindings->trailingNames[bindings->nonPositionalFormalStart - 1]
|
||||
.name();
|
||||
return paramName && name == paramName;
|
||||
|
@ -7475,7 +7474,7 @@ bool BytecodeEmitter::emitOptionalCalleeAndThis(ParseNode* callee,
|
|||
|
||||
switch (ParseNodeKind kind = callee->getKind()) {
|
||||
case ParseNodeKind::Name: {
|
||||
const ParserAtom* nameAtom = callee->as<NameNode>().name();
|
||||
RootedAtom nameAtom(cx, callee->as<NameNode>().name());
|
||||
if (!cone.emitNameCallee(nameAtom)) {
|
||||
// [stack] CALLEE THIS
|
||||
return false;
|
||||
|
@ -7571,7 +7570,7 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call,
|
|||
CallOrNewEmitter& cone) {
|
||||
switch (callee->getKind()) {
|
||||
case ParseNodeKind::Name: {
|
||||
const ParserAtom* nameAtom = callee->as<NameNode>().name();
|
||||
RootedAtom nameAtom(cx, callee->as<NameNode>().name());
|
||||
if (!cone.emitNameCallee(nameAtom)) {
|
||||
// [stack] CALLEE THIS
|
||||
return false;
|
||||
|
@ -7866,7 +7865,7 @@ bool BytecodeEmitter::emitCallOrNew(
|
|||
// Calls to "forceInterpreter", "callFunction",
|
||||
// "callContentFunction", or "resumeGenerator" in self-hosted
|
||||
// code generate inline bytecode.
|
||||
const ParserName* calleeName = calleeNode->as<NameNode>().name();
|
||||
RootedPropertyName calleeName(cx, calleeNode->as<NameNode>().name());
|
||||
if (calleeName == cx->parserNames().callFunction ||
|
||||
calleeName == cx->parserNames().callContentFunction ||
|
||||
calleeName == cx->parserNames().constructContentFunction) {
|
||||
|
@ -8378,7 +8377,7 @@ MOZ_NEVER_INLINE bool BytecodeEmitter::emitIncOrDec(UnaryNode* incDec) {
|
|||
// the comment on emitSwitch.
|
||||
MOZ_NEVER_INLINE bool BytecodeEmitter::emitLabeledStatement(
|
||||
const LabeledStatement* labeledStmt) {
|
||||
const ParserAtom* name = labeledStmt->label();
|
||||
RootedAtom name(cx, labeledStmt->label());
|
||||
LabelEmitter label(this);
|
||||
|
||||
label.emitLabel(name);
|
||||
|
@ -8528,9 +8527,10 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
|
|||
// is created elsewhere.
|
||||
ClassField* field = &propdef->as<ClassField>();
|
||||
if (field->name().getKind() == ParseNodeKind::ComputedName) {
|
||||
const ParserName* fieldKeys = field->isStatic()
|
||||
? cx->parserNames().dotStaticFieldKeys
|
||||
: cx->parserNames().dotFieldKeys;
|
||||
auto fieldKeysName = field->isStatic()
|
||||
? &JSAtomState::dotStaticFieldKeys
|
||||
: &JSAtomState::dotFieldKeys;
|
||||
HandlePropertyName fieldKeys = cx->parserNames().*fieldKeysName;
|
||||
if (!emitGetName(fieldKeys)) {
|
||||
// [stack] CTOR? OBJ ARRAY
|
||||
return false;
|
||||
|
@ -8642,8 +8642,7 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
|
|||
if (key->isKind(ParseNodeKind::NumberExpr)) {
|
||||
MOZ_ASSERT(accessorType == AccessorType::None);
|
||||
|
||||
const ParserAtom* keyAtom =
|
||||
key->as<NumericLiteral>().toAtom(compilationInfo);
|
||||
RootedAtom keyAtom(cx, key->as<NumericLiteral>().toAtom(cx));
|
||||
if (!keyAtom) {
|
||||
return false;
|
||||
}
|
||||
|
@ -8655,7 +8654,7 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
|
|||
key->isKind(ParseNodeKind::StringExpr)) {
|
||||
MOZ_ASSERT(accessorType == AccessorType::None);
|
||||
|
||||
const ParserAtom* keyAtom = key->as<NameNode>().atom();
|
||||
RootedAtom keyAtom(cx, key->as<NameNode>().atom());
|
||||
if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
|
||||
// [stack] CTOR? OBJ CTOR? VAL
|
||||
return false;
|
||||
|
@ -8760,7 +8759,7 @@ bool BytecodeEmitter::emitPropertyList(ListNode* obj, PropertyEmitter& pe,
|
|||
return false;
|
||||
}
|
||||
|
||||
const ParserAtom* keyAtom = key->as<NameNode>().atom();
|
||||
RootedAtom keyAtom(cx, key->as<NameNode>().atom());
|
||||
|
||||
if (!pe.emitInit(accessorType, keyAtom)) {
|
||||
return false;
|
||||
|
@ -8906,7 +8905,7 @@ bool BytecodeEmitter::emitDestructuringRestExclusionSetObjLiteral(
|
|||
break;
|
||||
}
|
||||
|
||||
const ParserAtom* atom = nullptr;
|
||||
JSAtom* atom;
|
||||
if (member->isKind(ParseNodeKind::MutateProto)) {
|
||||
atom = cx->parserNames().proto;
|
||||
} else {
|
||||
|
@ -9095,8 +9094,9 @@ bool BytecodeEmitter::emitCreateFieldKeys(ListNode* obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
const ParserName* fieldKeys = isStatic ? cx->parserNames().dotStaticFieldKeys
|
||||
: cx->parserNames().dotFieldKeys;
|
||||
auto fieldKeysName =
|
||||
isStatic ? &JSAtomState::dotStaticFieldKeys : &JSAtomState::dotFieldKeys;
|
||||
HandlePropertyName fieldKeys = cx->parserNames().*fieldKeysName;
|
||||
NameOpEmitter noe(this, fieldKeys, NameOpEmitter::Kind::Initialize);
|
||||
if (!noe.prepareForRhs()) {
|
||||
return false;
|
||||
|
@ -9246,8 +9246,7 @@ bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
|
|||
default:
|
||||
MOZ_CRASH("Invalid private method accessor type");
|
||||
}
|
||||
const ParserAtom* storedMethodAtom =
|
||||
storedMethodName.finishParserAtom(compilationInfo);
|
||||
RootedAtom storedMethodAtom(cx, storedMethodName.finishAtom());
|
||||
|
||||
// Emit the private method body and store it as a lexical var.
|
||||
if (!emitFunction(&propdef->as<ClassMethod>().method())) {
|
||||
|
@ -9297,9 +9296,11 @@ bool BytecodeEmitter::emitPrivateMethodInitializers(ClassEmitter& ce,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitPrivateMethodInitializer(
|
||||
ClassEmitter& ce, ParseNode* prop, ParseNode* propName,
|
||||
const ParserAtom* storedMethodAtom, AccessorType accessorType) {
|
||||
bool BytecodeEmitter::emitPrivateMethodInitializer(ClassEmitter& ce,
|
||||
ParseNode* prop,
|
||||
ParseNode* propName,
|
||||
HandleAtom storedMethodAtom,
|
||||
AccessorType accessorType) {
|
||||
// Emit the synthesized initializer function.
|
||||
FunctionNode* funNode = prop->as<ClassMethod>().initializerIfPrivate();
|
||||
if (!funNode) {
|
||||
|
@ -9548,7 +9549,7 @@ bool BytecodeEmitter::emitInitializeStaticFields(ListNode* classMembers) {
|
|||
|
||||
// Overwrite |.staticInitializers| and |.staticFieldKeys| with undefined to
|
||||
// avoid keeping the arrays alive indefinitely.
|
||||
auto clearStaticFieldSlot = [&](const ParserName* name) {
|
||||
auto clearStaticFieldSlot = [&](HandlePropertyName name) {
|
||||
NameOpEmitter noe(this, name, NameOpEmitter::Kind::SimpleAssignment);
|
||||
if (!noe.prepareForRhs()) {
|
||||
// [stack] ENV? VAL?
|
||||
|
@ -9953,7 +9954,7 @@ bool BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody) {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
const ParserName* paramName = bindingElement->as<NameNode>().name();
|
||||
RootedAtom paramName(cx, bindingElement->as<NameNode>().name());
|
||||
if (!fpe.emitRest(paramName)) {
|
||||
// [stack]
|
||||
return false;
|
||||
|
@ -10012,7 +10013,7 @@ bool BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody) {
|
|||
// [stack]
|
||||
return false;
|
||||
}
|
||||
const ParserAtom* paramName = bindingElement->as<NameNode>().name();
|
||||
RootedAtom paramName(cx, bindingElement->as<NameNode>().name());
|
||||
if (!fpe.emitDefaultEnd(paramName)) {
|
||||
// [stack]
|
||||
return false;
|
||||
|
@ -10021,7 +10022,7 @@ bool BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody) {
|
|||
continue;
|
||||
}
|
||||
|
||||
const ParserAtom* paramName = bindingElement->as<NameNode>().name();
|
||||
RootedAtom paramName(cx, bindingElement->as<NameNode>().name());
|
||||
if (!fpe.emitSimple(paramName)) {
|
||||
// [stack]
|
||||
return false;
|
||||
|
@ -10036,8 +10037,8 @@ bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
|
|||
|
||||
// [stack]
|
||||
|
||||
auto emitInitializeFunctionSpecialName = [](BytecodeEmitter* bce,
|
||||
const ParserName* name, JSOp op) {
|
||||
auto emitInitializeFunctionSpecialName =
|
||||
[](BytecodeEmitter* bce, HandlePropertyName name, JSOp op) {
|
||||
// A special name must be slotful, either on the frame or on the
|
||||
// call environment.
|
||||
MOZ_ASSERT(bce->lookupName(name).hasKnownSlot());
|
||||
|
@ -10094,10 +10095,11 @@ bool BytecodeEmitter::emitInitializeFunctionSpecialNames() {
|
|||
}
|
||||
|
||||
bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
|
||||
return emitLexicalInitialization(name->name());
|
||||
RootedAtom nameAtom(cx, name->name());
|
||||
return emitLexicalInitialization(nameAtom);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitLexicalInitialization(const ParserAtom* name) {
|
||||
bool BytecodeEmitter::emitLexicalInitialization(Handle<JSAtom*> name) {
|
||||
NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
|
||||
if (!noe.prepareForRhs()) {
|
||||
return false;
|
||||
|
@ -10148,7 +10150,7 @@ bool BytecodeEmitter::emitNewPrivateNames(ListNode* classMembers) {
|
|||
continue;
|
||||
}
|
||||
|
||||
const ParserAtom* privateName = elementName->as<NameNode>().name();
|
||||
RootedAtom privateName(cx, elementName->as<NameNode>().name());
|
||||
|
||||
// TODO: Add a new bytecode to create private names.
|
||||
if (!emitAtomOp(JSOp::GetIntrinsic, cx->parserNames().NewPrivateName)) {
|
||||
|
@ -10193,9 +10195,9 @@ bool BytecodeEmitter::emitNewPrivateNames(ListNode* classMembers) {
|
|||
bool BytecodeEmitter::emitClass(
|
||||
ClassNode* classNode,
|
||||
ClassNameKind nameKind /* = ClassNameKind::BindingName */,
|
||||
const ParserAtom* nameForAnonymousClass /* = nullptr */) {
|
||||
HandleAtom nameForAnonymousClass /* = nullptr */) {
|
||||
MOZ_ASSERT((nameKind == ClassNameKind::InferredName) ==
|
||||
bool(nameForAnonymousClass));
|
||||
(nameForAnonymousClass != nullptr));
|
||||
|
||||
ParseNode* heritageExpression = classNode->heritage();
|
||||
ListNode* classMembers = classNode->memberList();
|
||||
|
@ -10207,7 +10209,7 @@ bool BytecodeEmitter::emitClass(
|
|||
// [stack] NAME
|
||||
|
||||
ClassEmitter ce(this);
|
||||
const ParserAtom* innerName = nullptr;
|
||||
RootedAtom innerName(cx);
|
||||
ClassEmitter::Kind kind = ClassEmitter::Kind::Expression;
|
||||
if (ClassNames* names = classNode->names()) {
|
||||
MOZ_ASSERT(nameKind == ClassNameKind::BindingName);
|
||||
|
@ -10394,7 +10396,8 @@ bool BytecodeEmitter::emitExportDefault(BinaryNode* exportNode) {
|
|||
if (valueNode->isDirectRHSAnonFunction()) {
|
||||
MOZ_ASSERT(exportNode->right());
|
||||
|
||||
if (!emitAnonymousFunctionWithName(valueNode, cx->parserNames().default_)) {
|
||||
HandlePropertyName name = cx->parserNames().default_;
|
||||
if (!emitAnonymousFunctionWithName(valueNode, name)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -10458,8 +10461,7 @@ MOZ_NEVER_INLINE bool BytecodeEmitter::emitInstrumentationSlow(
|
|||
}
|
||||
// [stack] CALLBACK UNDEFINED
|
||||
|
||||
const ParserAtom* atom =
|
||||
RealmInstrumentation::getInstrumentationKindName(compilationInfo, kind);
|
||||
JSAtom* atom = RealmInstrumentation::getInstrumentationKindName(cx, kind);
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -209,22 +209,22 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
template <typename T, typename Predicate /* (T*) -> bool */>
|
||||
T* findInnermostNestableControl(Predicate predicate) const;
|
||||
|
||||
NameLocation lookupName(const ParserAtom* name);
|
||||
NameLocation lookupName(JSAtom* name);
|
||||
|
||||
// To implement Annex B and the formal parameter defaults scope semantics
|
||||
// requires accessing names that would otherwise be shadowed. This method
|
||||
// returns the access location of a name that is known to be bound in a
|
||||
// target scope.
|
||||
mozilla::Maybe<NameLocation> locationOfNameBoundInScope(
|
||||
const ParserAtom* name, EmitterScope* target);
|
||||
mozilla::Maybe<NameLocation> locationOfNameBoundInScope(JSAtom* name,
|
||||
EmitterScope* target);
|
||||
|
||||
// Get the location of a name known to be bound in the function scope,
|
||||
// starting at the source scope.
|
||||
mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(
|
||||
const ParserAtom* name, EmitterScope* source);
|
||||
JSAtom* name, EmitterScope* source);
|
||||
|
||||
mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(
|
||||
const ParserAtom* name) {
|
||||
JSAtom* name) {
|
||||
return locationOfNameBoundInFunctionScope(name, innermostEmitterScope());
|
||||
}
|
||||
|
||||
|
@ -240,8 +240,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
AbstractScopePtr innermostScope() const;
|
||||
ScopeIndex innermostScopeIndex() const;
|
||||
|
||||
MOZ_ALWAYS_INLINE MOZ_MUST_USE bool makeAtomIndex(const ParserAtom* atom,
|
||||
GCThingIndex* indexp) {
|
||||
MOZ_ALWAYS_INLINE
|
||||
MOZ_MUST_USE bool makeAtomIndex(JSAtom* atom, GCThingIndex* indexp) {
|
||||
MOZ_ASSERT(perScriptData().atomIndices());
|
||||
AtomIndexMap::AddPtr p = perScriptData().atomIndices()->lookupForAdd(atom);
|
||||
if (p) {
|
||||
|
@ -456,7 +456,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
MOZ_MUST_USE bool emitGCIndexOp(JSOp op, GCThingIndex index);
|
||||
|
||||
MOZ_MUST_USE bool emitAtomOp(
|
||||
JSOp op, const ParserAtom* atom,
|
||||
JSOp op, JSAtom* atom,
|
||||
ShouldInstrument shouldInstrument = ShouldInstrument::No);
|
||||
MOZ_MUST_USE bool emitAtomOp(
|
||||
JSOp op, GCThingIndex atomIndex,
|
||||
|
@ -518,9 +518,11 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
|
||||
MOZ_MUST_USE bool emitPrivateMethodInitializers(ClassEmitter& ce,
|
||||
ListNode* obj);
|
||||
MOZ_MUST_USE bool emitPrivateMethodInitializer(
|
||||
ClassEmitter& ce, ParseNode* prop, ParseNode* propName,
|
||||
const ParserAtom* storedMethodAtom, AccessorType accessorType);
|
||||
MOZ_MUST_USE bool emitPrivateMethodInitializer(ClassEmitter& ce,
|
||||
ParseNode* prop,
|
||||
ParseNode* propName,
|
||||
HandleAtom storedMethodAtom,
|
||||
AccessorType accessorType);
|
||||
|
||||
// To catch accidental misuse, emitUint16Operand/emit3 assert that they are
|
||||
// not used to unconditionally emit JSOp::GetLocal. Variable access should
|
||||
|
@ -532,16 +534,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot);
|
||||
MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
|
||||
|
||||
MOZ_MUST_USE bool emitGetNameAtLocation(const ParserAtom* name,
|
||||
MOZ_MUST_USE bool emitGetNameAtLocation(Handle<JSAtom*> name,
|
||||
const NameLocation& loc);
|
||||
MOZ_MUST_USE bool emitGetName(const ParserAtom* name) {
|
||||
MOZ_MUST_USE bool emitGetNameAtLocation(ImmutablePropertyNamePtr name,
|
||||
const NameLocation& loc) {
|
||||
return emitGetNameAtLocation(name.toHandle(), loc);
|
||||
}
|
||||
MOZ_MUST_USE bool emitGetName(Handle<JSAtom*> name) {
|
||||
return emitGetNameAtLocation(name, lookupName(name));
|
||||
}
|
||||
MOZ_MUST_USE bool emitGetName(ImmutablePropertyNamePtr name) {
|
||||
return emitGetNameAtLocation(name, lookupName(name));
|
||||
}
|
||||
MOZ_MUST_USE bool emitGetName(NameNode* name);
|
||||
MOZ_MUST_USE bool emitGetPrivateName(NameNode* name);
|
||||
MOZ_MUST_USE bool emitGetPrivateName(const ParserAtom* name);
|
||||
MOZ_MUST_USE bool emitGetPrivateName(JSAtom* name);
|
||||
|
||||
MOZ_MUST_USE bool emitTDZCheckIfNeeded(const ParserAtom* name,
|
||||
MOZ_MUST_USE bool emitTDZCheckIfNeeded(HandleAtom name,
|
||||
const NameLocation& loc,
|
||||
ValueIsOnStack isOnStack);
|
||||
|
||||
|
@ -551,7 +560,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
MOZ_MUST_USE bool emitSingleDeclaration(ListNode* declList, NameNode* decl,
|
||||
ParseNode* initializer);
|
||||
MOZ_MUST_USE bool emitAssignmentRhs(ParseNode* rhs,
|
||||
const ParserAtom* anonFunctionName);
|
||||
HandleAtom anonFunctionName);
|
||||
MOZ_MUST_USE bool emitAssignmentRhs(uint8_t offset);
|
||||
|
||||
MOZ_MUST_USE bool emitPrepareIteratorResult();
|
||||
|
@ -686,12 +695,12 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
MOZ_MUST_USE bool emitDefault(ParseNode* defaultExpr, ParseNode* pattern);
|
||||
|
||||
MOZ_MUST_USE bool emitAnonymousFunctionWithName(ParseNode* node,
|
||||
const ParserAtom* name);
|
||||
JS::Handle<JSAtom*> name);
|
||||
|
||||
MOZ_MUST_USE bool emitAnonymousFunctionWithComputedName(
|
||||
ParseNode* node, FunctionPrefixKind prefixKind);
|
||||
|
||||
MOZ_MUST_USE bool setFunName(FunctionBox* fun, const ParserAtom* name);
|
||||
MOZ_MUST_USE bool setFunName(FunctionBox* fun, JSAtom* name);
|
||||
MOZ_MUST_USE bool emitInitializer(ParseNode* initializer, ParseNode* pattern);
|
||||
|
||||
MOZ_MUST_USE bool emitCallSiteObjectArray(ListNode* cookedOrRaw,
|
||||
|
@ -789,13 +798,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
|
||||
MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead);
|
||||
|
||||
MOZ_MUST_USE bool emitBreak(const ParserName* label);
|
||||
MOZ_MUST_USE bool emitContinue(const ParserName* label);
|
||||
MOZ_MUST_USE bool emitBreak(PropertyName* label);
|
||||
MOZ_MUST_USE bool emitContinue(PropertyName* label);
|
||||
|
||||
MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
|
||||
MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
|
||||
MOZ_MUST_USE bool emitLexicalInitialization(NameNode* name);
|
||||
MOZ_MUST_USE bool emitLexicalInitialization(const ParserAtom* name);
|
||||
MOZ_MUST_USE bool emitLexicalInitialization(Handle<JSAtom*> name);
|
||||
|
||||
// Emit bytecode for the spread operator.
|
||||
//
|
||||
|
@ -820,8 +829,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
|
||||
MOZ_MUST_USE bool emitClass(
|
||||
ClassNode* classNode, ClassNameKind nameKind = ClassNameKind::BindingName,
|
||||
const ParserAtom* nameForAnonymousClass = nullptr);
|
||||
|
||||
JS::Handle<JSAtom*> nameForAnonymousClass = nullptr);
|
||||
MOZ_MUST_USE bool emitSuperElemOperands(
|
||||
PropertyByValue* elem, EmitElemOption opts = EmitElemOption::Get);
|
||||
MOZ_MUST_USE bool emitSuperGetElem(PropertyByValue* elem,
|
||||
|
|
|
@ -58,12 +58,8 @@ bool js::frontend::EmitScriptThingsVector(JSContext* cx,
|
|||
mozilla::Span<JS::GCCellPtr>& output;
|
||||
|
||||
bool operator()(const ScriptAtom& data) {
|
||||
auto maybeAtom = data->toJSAtom(cx);
|
||||
if (maybeAtom.isErr()) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(maybeAtom.unwrap());
|
||||
output[i] = JS::GCCellPtr(maybeAtom.unwrap());
|
||||
JSAtom* atom = data;
|
||||
output[i] = JS::GCCellPtr(atom);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -94,7 +90,7 @@ bool js::frontend::EmitScriptThingsVector(JSContext* cx,
|
|||
|
||||
bool operator()(const ObjLiteralIndex& index) {
|
||||
ObjLiteralStencil& data = compilationInfo.objLiteralData[index];
|
||||
JSObject* obj = data.create(cx, compilationInfo);
|
||||
JSObject* obj = data.create(cx);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
@ -167,9 +163,8 @@ void CGScopeNoteList::recordEndImpl(uint32_t index, uint32_t offset) {
|
|||
list[index].length = offset - list[index].start;
|
||||
}
|
||||
|
||||
JSObject* ObjLiteralStencil::create(JSContext* cx,
|
||||
CompilationInfo& compilationInfo) const {
|
||||
return InterpretObjLiteral(cx, compilationInfo, atoms_, writer_);
|
||||
JSObject* ObjLiteralStencil::create(JSContext* cx) const {
|
||||
return InterpretObjLiteral(cx, atoms_, writer_);
|
||||
}
|
||||
|
||||
BytecodeSection::BytecodeSection(JSContext* cx, uint32_t lineNum)
|
||||
|
|
|
@ -55,7 +55,7 @@ struct MOZ_STACK_CLASS GCThingList {
|
|||
explicit GCThingList(JSContext* cx, CompilationInfo& compilationInfo)
|
||||
: compilationInfo(compilationInfo), vector(cx) {}
|
||||
|
||||
MOZ_MUST_USE bool append(const ParserAtom* atom, GCThingIndex* index) {
|
||||
MOZ_MUST_USE bool append(JSAtom* atom, GCThingIndex* index) {
|
||||
*index = GCThingIndex(vector.length());
|
||||
return vector.append(mozilla::AsVariant(std::move(atom)));
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ CallOrNewEmitter::CallOrNewEmitter(BytecodeEmitter* bce, JSOp op,
|
|||
MOZ_ASSERT(isCall() || isNew() || isSuperCall());
|
||||
}
|
||||
|
||||
bool CallOrNewEmitter::emitNameCallee(const ParserAtom* name) {
|
||||
bool CallOrNewEmitter::emitNameCallee(Handle<JSAtom*> name) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
|
||||
NameOpEmitter noe(
|
||||
|
|
|
@ -290,7 +290,7 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
|
|||
}
|
||||
|
||||
public:
|
||||
MOZ_MUST_USE bool emitNameCallee(const ParserAtom* name);
|
||||
MOZ_MUST_USE bool emitNameCallee(Handle<JSAtom*> name);
|
||||
MOZ_MUST_USE PropOpEmitter& prepareForPropCallee(bool isSuperProp);
|
||||
MOZ_MUST_USE ElemOpEmitter& prepareForElemCallee(bool isSuperElem,
|
||||
bool isPrivateElem);
|
||||
|
|
|
@ -290,14 +290,6 @@ struct MOZ_RAII CompilationInfo : public JS::CustomAutoRooter {
|
|||
|
||||
void trace(JSTracer* trc) final;
|
||||
|
||||
JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
|
||||
return parserAtom->toJSAtom(cx).unwrapOr(nullptr);
|
||||
}
|
||||
const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
|
||||
auto result = parserAtoms.internJSAtom(cx, atom);
|
||||
return result.unwrapOr(nullptr);
|
||||
}
|
||||
|
||||
// To avoid any misuses, make sure this is neither copyable,
|
||||
// movable or assignable.
|
||||
CompilationInfo(const CompilationInfo&) = delete;
|
||||
|
|
|
@ -149,15 +149,6 @@ class EitherParser : public BCEParserHandle {
|
|||
matcher{offset, line, column};
|
||||
return parser.match(std::move(matcher));
|
||||
}
|
||||
|
||||
JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
|
||||
ParserSharedBase& base = parser.match(detail::ParserSharedBaseMatcher());
|
||||
return base.liftParserAtomToJSAtom(parserAtom);
|
||||
}
|
||||
const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
|
||||
ParserSharedBase& base = parser.match(detail::ParserSharedBaseMatcher());
|
||||
return base.lowerJSAtomToParserAtom(atom);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
|
|
|
@ -34,7 +34,7 @@ bool EmitterScope::ensureCache(BytecodeEmitter* bce) {
|
|||
}
|
||||
|
||||
bool EmitterScope::checkSlotLimits(BytecodeEmitter* bce,
|
||||
const ParserBindingIter& bi) {
|
||||
const BindingIter& bi) {
|
||||
if (bi.nextFrameSlot() >= LOCALNO_LIMIT ||
|
||||
bi.nextEnvironmentSlot() >= ENVCOORD_SLOT_LIMIT) {
|
||||
bce->reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
|
||||
|
@ -61,7 +61,7 @@ bool EmitterScope::checkEnvironmentChainLength(BytecodeEmitter* bce) {
|
|||
}
|
||||
|
||||
void EmitterScope::updateFrameFixedSlots(BytecodeEmitter* bce,
|
||||
const ParserBindingIter& bi) {
|
||||
const BindingIter& bi) {
|
||||
nextFrameSlot_ = bi.nextFrameSlot();
|
||||
if (nextFrameSlot_ > bce->maxFixedSlots) {
|
||||
bce->maxFixedSlots = nextFrameSlot_;
|
||||
|
@ -72,7 +72,7 @@ void EmitterScope::updateFrameFixedSlots(BytecodeEmitter* bce,
|
|||
bce->maxFixedSlots == 0);
|
||||
}
|
||||
|
||||
bool EmitterScope::putNameInCache(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
bool EmitterScope::putNameInCache(BytecodeEmitter* bce, JSAtom* name,
|
||||
NameLocation loc) {
|
||||
NameLocationMap& cache = *nameCache_;
|
||||
NameLocationMap::AddPtr p = cache.lookupForAdd(name);
|
||||
|
@ -85,7 +85,7 @@ bool EmitterScope::putNameInCache(BytecodeEmitter* bce, const ParserAtom* name,
|
|||
}
|
||||
|
||||
Maybe<NameLocation> EmitterScope::lookupInCache(BytecodeEmitter* bce,
|
||||
const ParserAtom* name) {
|
||||
JSAtom* name) {
|
||||
if (NameLocationMap::Ptr p = nameCache_->lookup(name)) {
|
||||
return Some(p->value().wrapped);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ mozilla::Maybe<ScopeIndex> EmitterScope::enclosingScopeIndex(
|
|||
}
|
||||
|
||||
/* static */
|
||||
bool EmitterScope::nameCanBeFree(BytecodeEmitter* bce, const ParserAtom* name) {
|
||||
bool EmitterScope::nameCanBeFree(BytecodeEmitter* bce, JSAtom* name) {
|
||||
// '.generator' cannot be accessed by name.
|
||||
return name != bce->cx->parserNames().dotGenerator;
|
||||
}
|
||||
|
@ -168,9 +168,6 @@ static bool NameIsOnEnvironment(Scope* scope, JSAtom* name) {
|
|||
/* static */
|
||||
NameLocation EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope,
|
||||
uint8_t hops) {
|
||||
// TODO-Stencil
|
||||
// This needs to be handled properly by snapshotting enclosing scopes.
|
||||
|
||||
for (ScopeIter si(scope); si; si++) {
|
||||
MOZ_ASSERT(NameIsOnEnvironment(si.scope(), name));
|
||||
|
||||
|
@ -287,8 +284,7 @@ NameLocation EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope,
|
|||
MOZ_CRASH("Malformed scope chain");
|
||||
}
|
||||
|
||||
NameLocation EmitterScope::searchAndCache(BytecodeEmitter* bce,
|
||||
const ParserAtom* name) {
|
||||
NameLocation EmitterScope::searchAndCache(BytecodeEmitter* bce, JSAtom* name) {
|
||||
Maybe<NameLocation> loc;
|
||||
uint8_t hops = hasEnvironment() ? 1 : 0;
|
||||
DebugOnly<bool> inCurrentScript = enclosingInFrame();
|
||||
|
@ -317,25 +313,9 @@ NameLocation EmitterScope::searchAndCache(BytecodeEmitter* bce,
|
|||
// If the name is not found in the current compilation, walk the Scope
|
||||
// chain encompassing the compilation.
|
||||
if (!loc) {
|
||||
// TODO-Stencil
|
||||
// Here, we convert our name into a JSAtom*, and hard-crash on failure
|
||||
// to allocate. This conversion should not be required as we should be
|
||||
// able to iterate up snapshotted scope chains that use parser atoms.
|
||||
//
|
||||
// This will be fixed when parser scopes are snapshotted, and
|
||||
// `searchInEnclosingScope` changes to accepting a `const ParserAtom*`
|
||||
// instead of a `JSAtom*`.
|
||||
//
|
||||
// See bug 1660275.
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
JSAtom* jsname = bce->compilationInfo.liftParserAtomToJSAtom(name);
|
||||
if (!jsname) {
|
||||
oomUnsafe.crash("EmitterScope::searchAndCache");
|
||||
}
|
||||
|
||||
inCurrentScript = false;
|
||||
loc = Some(searchInEnclosingScope(
|
||||
jsname, bce->compilationInfo.enclosingScope, hops));
|
||||
loc = Some(searchInEnclosingScope(name, bce->compilationInfo.enclosingScope,
|
||||
hops));
|
||||
}
|
||||
|
||||
// Each script has its own frame. A free name that is accessed
|
||||
|
@ -433,7 +413,7 @@ void EmitterScope::dump(BytecodeEmitter* bce) {
|
|||
for (NameLocationMap::Range r = nameCache_->all(); !r.empty(); r.popFront()) {
|
||||
const NameLocation& l = r.front().value();
|
||||
|
||||
UniqueChars bytes = ParserAtomToPrintableString(bce->cx, r.front().key());
|
||||
UniqueChars bytes = AtomToPrintableString(bce->cx, r.front().key());
|
||||
if (!bytes) {
|
||||
return;
|
||||
}
|
||||
|
@ -481,7 +461,7 @@ void EmitterScope::dump(BytecodeEmitter* bce) {
|
|||
}
|
||||
|
||||
bool EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind,
|
||||
ParserLexicalScopeData* bindings) {
|
||||
Handle<LexicalScope::Data*> bindings) {
|
||||
MOZ_ASSERT(kind != ScopeKind::NamedLambda &&
|
||||
kind != ScopeKind::StrictNamedLambda);
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
@ -493,7 +473,7 @@ bool EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind,
|
|||
// Resolve bindings.
|
||||
TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
|
||||
uint32_t firstFrameSlot = frameSlotStart();
|
||||
ParserBindingIter bi(*bindings, firstFrameSlot, /* isNamedLambda = */ false);
|
||||
BindingIter bi(*bindings, firstFrameSlot, /* isNamedLambda = */ false);
|
||||
for (; bi; bi++) {
|
||||
if (!checkSlotLimits(bce, bi)) {
|
||||
return false;
|
||||
|
@ -554,7 +534,7 @@ bool EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox) {
|
|||
return false;
|
||||
}
|
||||
|
||||
ParserBindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT,
|
||||
BindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT,
|
||||
/* isNamedLambda = */ true);
|
||||
MOZ_ASSERT(bi.kind() == BindingKind::NamedLambdaCallee);
|
||||
|
||||
|
@ -602,7 +582,7 @@ bool EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox) {
|
|||
if (bindings) {
|
||||
NameLocationMap& cache = *nameCache_;
|
||||
|
||||
ParserBindingIter bi(*bindings, funbox->hasParameterExprs);
|
||||
BindingIter bi(*bindings, funbox->hasParameterExprs);
|
||||
for (; bi; bi++) {
|
||||
if (!checkSlotLimits(bce, bi)) {
|
||||
return false;
|
||||
|
@ -644,7 +624,7 @@ bool EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox) {
|
|||
// bindings and have TDZ.
|
||||
if (funbox->hasParameterExprs && nextFrameSlot_) {
|
||||
uint32_t paramFrameSlotEnd = 0;
|
||||
for (ParserBindingIter bi(*bindings, true); bi; bi++) {
|
||||
for (BindingIter bi(*bindings, true); bi; bi++) {
|
||||
if (!BindingKindIsLexical(bi.kind())) {
|
||||
break;
|
||||
}
|
||||
|
@ -695,7 +675,7 @@ bool EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce,
|
|||
// Resolve body-level bindings, if there are any.
|
||||
uint32_t firstFrameSlot = frameSlotStart();
|
||||
if (auto bindings = funbox->extraVarScopeBindings()) {
|
||||
ParserBindingIter bi(*bindings, firstFrameSlot);
|
||||
BindingIter bi(*bindings, firstFrameSlot);
|
||||
for (; bi; bi++) {
|
||||
if (!checkSlotLimits(bce, bi)) {
|
||||
return false;
|
||||
|
@ -748,13 +728,13 @@ bool EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce,
|
|||
return checkEnvironmentChainLength(bce);
|
||||
}
|
||||
|
||||
class DynamicBindingIter : public ParserBindingIter {
|
||||
class DynamicBindingIter : public BindingIter {
|
||||
public:
|
||||
explicit DynamicBindingIter(GlobalSharedContext* sc)
|
||||
: ParserBindingIter(*sc->bindings) {}
|
||||
: BindingIter(*sc->bindings) {}
|
||||
|
||||
explicit DynamicBindingIter(EvalSharedContext* sc)
|
||||
: ParserBindingIter(*sc->bindings, /* strict = */ false) {
|
||||
: BindingIter(*sc->bindings, /* strict = */ false) {
|
||||
MOZ_ASSERT(!sc->strict());
|
||||
}
|
||||
|
||||
|
@ -776,11 +756,6 @@ bool EmitterScope::enterGlobal(BytecodeEmitter* bce,
|
|||
GlobalSharedContext* globalsc) {
|
||||
MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck());
|
||||
|
||||
// TODO-Stencil
|
||||
// This is another snapshot-sensitive location.
|
||||
// The incoming atoms from the global scope object should be snapshotted.
|
||||
// For now, converting them to ParserAtoms here individually.
|
||||
|
||||
bce->setVarEmitterScope(this);
|
||||
|
||||
if (!ensureCache(bce)) {
|
||||
|
@ -825,7 +800,7 @@ bool EmitterScope::enterGlobal(BytecodeEmitter* bce,
|
|||
|
||||
for (DynamicBindingIter bi(globalsc); bi; bi++) {
|
||||
NameLocation loc = NameLocation::fromBinding(bi.kind(), bi.location());
|
||||
const ParserAtom* name = bi.name();
|
||||
JSAtom* name = bi.name();
|
||||
if (!putNameInCache(bce, name, loc)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -935,8 +910,8 @@ bool EmitterScope::enterModule(BytecodeEmitter* bce,
|
|||
// Resolve body-level bindings, if there are any.
|
||||
TDZCheckCache* tdzCache = bce->innermostTDZCheckCache;
|
||||
Maybe<uint32_t> firstLexicalFrameSlot;
|
||||
if (ParserModuleScopeData* bindings = modulesc->bindings) {
|
||||
ParserBindingIter bi(*bindings);
|
||||
if (ModuleScope::Data* bindings = modulesc->bindings) {
|
||||
BindingIter bi(*bindings);
|
||||
for (; bi; bi++) {
|
||||
if (!checkSlotLimits(bce, bi)) {
|
||||
return false;
|
||||
|
@ -1092,15 +1067,14 @@ mozilla::Maybe<ScopeIndex> EmitterScope::scopeIndex(
|
|||
return bce->perScriptData().gcThingList().getScopeIndex(index());
|
||||
}
|
||||
|
||||
NameLocation EmitterScope::lookup(BytecodeEmitter* bce,
|
||||
const ParserAtom* name) {
|
||||
NameLocation EmitterScope::lookup(BytecodeEmitter* bce, JSAtom* name) {
|
||||
if (Maybe<NameLocation> loc = lookupInCache(bce, name)) {
|
||||
return *loc;
|
||||
}
|
||||
return searchAndCache(bce, name);
|
||||
}
|
||||
|
||||
Maybe<NameLocation> EmitterScope::locationBoundInScope(const ParserAtom* name,
|
||||
Maybe<NameLocation> EmitterScope::locationBoundInScope(JSAtom* name,
|
||||
EmitterScope* target) {
|
||||
// The target scope must be an intra-frame enclosing scope of this
|
||||
// one. Count the number of extra hops to reach it.
|
||||
|
|
|
@ -66,27 +66,27 @@ class EmitterScope : public Nestable<EmitterScope> {
|
|||
MOZ_MUST_USE bool ensureCache(BytecodeEmitter* bce);
|
||||
|
||||
MOZ_MUST_USE bool checkSlotLimits(BytecodeEmitter* bce,
|
||||
const ParserBindingIter& bi);
|
||||
const BindingIter& bi);
|
||||
|
||||
MOZ_MUST_USE bool checkEnvironmentChainLength(BytecodeEmitter* bce);
|
||||
|
||||
void updateFrameFixedSlots(BytecodeEmitter* bce, const ParserBindingIter& bi);
|
||||
void updateFrameFixedSlots(BytecodeEmitter* bce, const BindingIter& bi);
|
||||
|
||||
MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
MOZ_MUST_USE bool putNameInCache(BytecodeEmitter* bce, JSAtom* name,
|
||||
NameLocation loc);
|
||||
|
||||
mozilla::Maybe<NameLocation> lookupInCache(BytecodeEmitter* bce,
|
||||
const ParserAtom* name);
|
||||
JSAtom* name);
|
||||
|
||||
EmitterScope* enclosing(BytecodeEmitter** bce) const;
|
||||
|
||||
mozilla::Maybe<ScopeIndex> enclosingScopeIndex(BytecodeEmitter* bce) const;
|
||||
|
||||
static bool nameCanBeFree(BytecodeEmitter* bce, const ParserAtom* name);
|
||||
static bool nameCanBeFree(BytecodeEmitter* bce, JSAtom* name);
|
||||
|
||||
static NameLocation searchInEnclosingScope(JSAtom* name, Scope* scope,
|
||||
uint8_t hops);
|
||||
NameLocation searchAndCache(BytecodeEmitter* bce, const ParserAtom* name);
|
||||
NameLocation searchAndCache(BytecodeEmitter* bce, JSAtom* name);
|
||||
|
||||
MOZ_MUST_USE bool internEmptyGlobalScopeAsBody(BytecodeEmitter* bce);
|
||||
|
||||
|
@ -109,7 +109,7 @@ class EmitterScope : public Nestable<EmitterScope> {
|
|||
void dump(BytecodeEmitter* bce);
|
||||
|
||||
MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind,
|
||||
ParserLexicalScopeData* bindings);
|
||||
Handle<LexicalScope::Data*> 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,
|
||||
|
@ -152,9 +152,9 @@ class EmitterScope : public Nestable<EmitterScope> {
|
|||
return Nestable<EmitterScope>::enclosing();
|
||||
}
|
||||
|
||||
NameLocation lookup(BytecodeEmitter* bce, const ParserAtom* name);
|
||||
NameLocation lookup(BytecodeEmitter* bce, JSAtom* name);
|
||||
|
||||
mozilla::Maybe<NameLocation> locationBoundInScope(const ParserAtom* name,
|
||||
mozilla::Maybe<NameLocation> locationBoundInScope(JSAtom* name,
|
||||
EmitterScope* target);
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "frontend/FoldConstants.h"
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/Range.h"
|
||||
|
||||
#include "jslibmath.h"
|
||||
#include "jsnum.h"
|
||||
|
@ -17,7 +16,6 @@
|
|||
#include "frontend/Parser.h"
|
||||
#include "js/Conversions.h"
|
||||
#include "js/friend/StackLimits.h" // js::CheckRecursionLimit
|
||||
#include "js/Vector.h"
|
||||
#include "vm/StringType.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -464,7 +462,7 @@ static bool FoldType(FoldInfo info, ParseNode** pnp, ParseNodeKind kind) {
|
|||
case ParseNodeKind::NumberExpr:
|
||||
if (pn->isKind(ParseNodeKind::StringExpr)) {
|
||||
double d;
|
||||
if (!pn->as<NameNode>().atom()->toNumber(info.cx(), &d)) {
|
||||
if (!StringToNumber(info.cx(), pn->as<NameNode>().atom(), &d)) {
|
||||
return false;
|
||||
}
|
||||
if (!TryReplaceNode(
|
||||
|
@ -476,8 +474,7 @@ static bool FoldType(FoldInfo info, ParseNode** pnp, ParseNodeKind kind) {
|
|||
|
||||
case ParseNodeKind::StringExpr:
|
||||
if (pn->isKind(ParseNodeKind::NumberExpr)) {
|
||||
const ParserAtom* atom =
|
||||
pn->as<NumericLiteral>().toAtom(info.compilationInfo);
|
||||
JSAtom* atom = pn->as<NumericLiteral>().toAtom(info.cx());
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
|
@ -579,21 +576,21 @@ static bool FoldTypeOfExpr(FoldInfo info, ParseNode** nodePtr) {
|
|||
ParseNode* expr = node->kid();
|
||||
|
||||
// Constant-fold the entire |typeof| if given a constant with known type.
|
||||
const ParserName* result = nullptr;
|
||||
RootedPropertyName result(info.cx());
|
||||
if (expr->isKind(ParseNodeKind::StringExpr) ||
|
||||
expr->isKind(ParseNodeKind::TemplateStringExpr)) {
|
||||
result = info.cx()->parserNames().string;
|
||||
result = info.cx()->names().string;
|
||||
} else if (expr->isKind(ParseNodeKind::NumberExpr)) {
|
||||
result = info.cx()->parserNames().number;
|
||||
result = info.cx()->names().number;
|
||||
} else if (expr->isKind(ParseNodeKind::BigIntExpr)) {
|
||||
result = info.cx()->parserNames().bigint;
|
||||
result = info.cx()->names().bigint;
|
||||
} else if (expr->isKind(ParseNodeKind::NullExpr)) {
|
||||
result = info.cx()->parserNames().object;
|
||||
result = info.cx()->names().object;
|
||||
} else if (expr->isKind(ParseNodeKind::TrueExpr) ||
|
||||
expr->isKind(ParseNodeKind::FalseExpr)) {
|
||||
result = info.cx()->parserNames().boolean;
|
||||
result = info.cx()->names().boolean;
|
||||
} else if (expr->is<FunctionNode>()) {
|
||||
result = info.cx()->parserNames().function;
|
||||
result = info.cx()->names().function;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
|
@ -1084,9 +1081,9 @@ static bool FoldElement(FoldInfo info, ParseNode** nodePtr) {
|
|||
|
||||
ParseNode* expr = &elem->expression();
|
||||
ParseNode* key = &elem->key();
|
||||
const ParserName* name = nullptr;
|
||||
PropertyName* name = nullptr;
|
||||
if (key->isKind(ParseNodeKind::StringExpr)) {
|
||||
const ParserAtom* atom = key->as<NameNode>().atom();
|
||||
JSAtom* atom = key->as<NameNode>().atom();
|
||||
uint32_t index;
|
||||
|
||||
if (atom->isIndex(&index)) {
|
||||
|
@ -1099,7 +1096,7 @@ static bool FoldElement(FoldInfo info, ParseNode** nodePtr) {
|
|||
}
|
||||
key = &elem->key();
|
||||
} else {
|
||||
name = atom->asName();
|
||||
name = atom->asPropertyName();
|
||||
}
|
||||
} else if (key->isKind(ParseNodeKind::NumberExpr)) {
|
||||
auto* numeric = &key->as<NumericLiteral>();
|
||||
|
@ -1108,11 +1105,11 @@ static bool FoldElement(FoldInfo info, ParseNode** nodePtr) {
|
|||
// Optimization 2: We have something like expr[3.14]. The number
|
||||
// isn't an array index, so it converts to a string ("3.14"),
|
||||
// enabling optimization 3 below.
|
||||
const ParserAtom* atom = numeric->toAtom(info.compilationInfo);
|
||||
JSAtom* atom = numeric->toAtom(info.cx());
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
name = atom->asName();
|
||||
name = atom->asPropertyName();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1205,16 +1202,15 @@ static bool FoldAdd(FoldInfo info, ParseNode** nodePtr) {
|
|||
break;
|
||||
}
|
||||
|
||||
Vector<const ParserAtom*, 8> accum(info.cx());
|
||||
RootedString combination(info.cx());
|
||||
RootedString tmp(info.cx());
|
||||
do {
|
||||
// Create a vector of all the folded strings and concatenate them.
|
||||
// Create a rope of the current string and all succeeding
|
||||
// constants that we can convert to strings, then atomize it
|
||||
// and replace them all with that fresh string.
|
||||
MOZ_ASSERT((*current)->isKind(ParseNodeKind::StringExpr));
|
||||
|
||||
accum.clear();
|
||||
const ParserAtom* atom = (*current)->as<NameNode>().atom();
|
||||
if (!accum.append(atom)) {
|
||||
return false;
|
||||
}
|
||||
combination = (*current)->as<NameNode>().atom();
|
||||
|
||||
do {
|
||||
// Try folding the next operand to a string.
|
||||
|
@ -1227,9 +1223,10 @@ static bool FoldAdd(FoldInfo info, ParseNode** nodePtr) {
|
|||
break;
|
||||
}
|
||||
|
||||
// Add this string to the accumulator and remove the node.
|
||||
const ParserAtom* nextAtom = (*next)->as<NameNode>().atom();
|
||||
if (!accum.append(nextAtom)) {
|
||||
// Add this string to the combination and remove the node.
|
||||
tmp = (*next)->as<NameNode>().atom();
|
||||
combination = ConcatStrings<CanGC>(info.cx(), combination, tmp);
|
||||
if (!combination) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1239,19 +1236,13 @@ static bool FoldAdd(FoldInfo info, ParseNode** nodePtr) {
|
|||
node->unsafeDecrementCount();
|
||||
} while (*next);
|
||||
|
||||
// Construct the concatenated atom.
|
||||
const ParserAtom* combination =
|
||||
info.compilationInfo.parserAtoms
|
||||
.concatAtoms(info.cx(),
|
||||
mozilla::Range(accum.begin(), accum.length()))
|
||||
.unwrapOr(nullptr);
|
||||
// Replace |current|'s string with the entire combination.
|
||||
MOZ_ASSERT((*current)->isKind(ParseNodeKind::StringExpr));
|
||||
combination = AtomizeString(info.cx(), combination);
|
||||
if (!combination) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Replace |current|'s string with the entire combination.
|
||||
MOZ_ASSERT((*current)->isKind(ParseNodeKind::StringExpr));
|
||||
(*current)->as<NameNode>().setAtom(combination);
|
||||
(*current)->as<NameNode>().setAtom(&combination->asAtom());
|
||||
|
||||
// If we're out of nodes, we're done.
|
||||
if (!*next) {
|
||||
|
|
|
@ -21,22 +21,27 @@
|
|||
#include "frontend/BytecodeSection.h" // EmitScriptThingsVector
|
||||
#include "frontend/CompilationInfo.h" // CompilationInfo
|
||||
#include "frontend/Parser.h" // NewEmptyLexicalScopeData, NewEmptyGlobalScopeData, NewEmptyVarScopeData, NewEmptyFunctionScopeData
|
||||
#include "frontend/ParserAtom.h" // ParserAtomsTable
|
||||
#include "frontend/smoosh_generated.h" // CVec, Smoosh*, smoosh_*
|
||||
#include "frontend/SourceNotes.h" // SrcNote
|
||||
#include "frontend/Stencil.h" // ScopeStencil, RegExpIndex, FunctionIndex, NullScriptThing
|
||||
#include "frontend/TokenStream.h" // TokenStreamAnyChars
|
||||
#include "gc/Rooting.h" // RootedScriptSourceObject
|
||||
#include "irregexp/RegExpAPI.h" // irregexp::CheckPatternSyntax
|
||||
#include "js/CharacterEncoding.h" // JS::UTF8Chars, UTF8CharsToNewTwoByteCharsZ
|
||||
#include "js/GCAPI.h" // JS::AutoCheckCannotGC
|
||||
#include "js/GCVector.h" // JS::RootedVector
|
||||
#include "js/HeapAPI.h" // JS::GCCellPtr
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "js/RootingAPI.h" // JS::MutableHandle
|
||||
#include "js/RootingAPI.h" // JS::Handle, JS::Rooted
|
||||
#include "js/TypeDecls.h" // Rooted{Script,Value,String,Object}, JS*:HandleVector, JS::MutableHandleVector
|
||||
#include "js/UniquePtr.h" // js::UniquePtr
|
||||
#include "js/Utility.h" // JS::UniqueTwoByteChars, StringBufferArena
|
||||
#include "vm/JSAtom.h" // AtomizeUTF8Chars
|
||||
#include "vm/JSScript.h" // JSScript
|
||||
#include "vm/Scope.h" // BindingName
|
||||
#include "vm/ScopeKind.h" // ScopeKind
|
||||
#include "vm/SharedStencil.h" // ImmutableScriptData, ScopeNote, TryNote, GCThingIndex
|
||||
#include "vm/StringType.h" // JSAtom
|
||||
|
||||
#include "vm/JSContext-inl.h" // AutoKeepAtoms (used by BytecodeCompiler)
|
||||
|
||||
|
@ -51,10 +56,10 @@ namespace js {
|
|||
namespace frontend {
|
||||
|
||||
// Given the result of SmooshMonkey's parser, Convert the list of atoms into
|
||||
// the list of ParserAtoms.
|
||||
// the list of JSAtoms.
|
||||
bool ConvertAtoms(JSContext* cx, const SmooshResult& result,
|
||||
CompilationInfo& compilationInfo,
|
||||
Vector<const ParserAtom*>& allAtoms) {
|
||||
JS::MutableHandleVector<JSAtom*> allAtoms) {
|
||||
size_t numAtoms = result.all_atoms_len;
|
||||
|
||||
if (!allAtoms.reserve(numAtoms)) {
|
||||
|
@ -62,11 +67,9 @@ bool ConvertAtoms(JSContext* cx, const SmooshResult& result,
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < numAtoms; i++) {
|
||||
auto s = reinterpret_cast<const mozilla::Utf8Unit*>(
|
||||
smoosh_get_atom_at(result, i));
|
||||
auto s = smoosh_get_atom_at(result, i);
|
||||
auto len = smoosh_get_atom_len_at(result, i);
|
||||
const ParserAtom* atom =
|
||||
compilationInfo.parserAtoms.internUtf8(cx, s, len).unwrapOr(nullptr);
|
||||
JSAtom* atom = AtomizeUTF8Chars(cx, s, len);
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
|
@ -77,22 +80,20 @@ bool ConvertAtoms(JSContext* cx, const SmooshResult& result,
|
|||
}
|
||||
|
||||
void CopyBindingNames(JSContext* cx, CVec<SmooshBindingName>& from,
|
||||
Vector<const ParserAtom*>& allAtoms,
|
||||
ParserBindingName* to) {
|
||||
JS::HandleVector<JSAtom*> allAtoms, BindingName* to) {
|
||||
// We're setting trailing array's content before setting its length.
|
||||
JS::AutoCheckCannotGC nogc(cx);
|
||||
|
||||
size_t numBindings = from.len;
|
||||
for (size_t i = 0; i < numBindings; i++) {
|
||||
SmooshBindingName& name = from.data[i];
|
||||
new (mozilla::KnownNotNull, &to[i]) ParserBindingName(
|
||||
new (mozilla::KnownNotNull, &to[i]) BindingName(
|
||||
allAtoms[name.name], name.is_closed_over, name.is_top_level_function);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyBindingNames(JSContext* cx, CVec<COption<SmooshBindingName>>& from,
|
||||
Vector<const ParserAtom*>& allAtoms,
|
||||
ParserBindingName* to) {
|
||||
JS::HandleVector<JSAtom*> allAtoms, BindingName* to) {
|
||||
// We're setting trailing array's content before setting its length.
|
||||
JS::AutoCheckCannotGC nogc(cx);
|
||||
|
||||
|
@ -101,11 +102,10 @@ void CopyBindingNames(JSContext* cx, CVec<COption<SmooshBindingName>>& from,
|
|||
COption<SmooshBindingName>& maybeName = from.data[i];
|
||||
if (maybeName.IsSome()) {
|
||||
SmooshBindingName& name = maybeName.AsSome();
|
||||
new (mozilla::KnownNotNull, &to[i]) ParserBindingName(
|
||||
new (mozilla::KnownNotNull, &to[i]) BindingName(
|
||||
allAtoms[name.name], name.is_closed_over, name.is_top_level_function);
|
||||
} else {
|
||||
new (mozilla::KnownNotNull, &to[i])
|
||||
ParserBindingName(nullptr, false, false);
|
||||
new (mozilla::KnownNotNull, &to[i]) BindingName(nullptr, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ void CopyBindingNames(JSContext* cx, CVec<COption<SmooshBindingName>>& from,
|
|||
// Given the result of SmooshMonkey's parser, convert a list of scope data
|
||||
// into a list of ScopeStencil.
|
||||
bool ConvertScopeStencil(JSContext* cx, const SmooshResult& result,
|
||||
Vector<const ParserAtom*>& allAtoms,
|
||||
JS::HandleVector<JSAtom*> allAtoms,
|
||||
CompilationInfo& compilationInfo) {
|
||||
auto& alloc = compilationInfo.allocScope.alloc();
|
||||
|
||||
|
@ -126,8 +126,8 @@ bool ConvertScopeStencil(JSContext* cx, const SmooshResult& result,
|
|||
auto& global = scopeData.AsGlobal();
|
||||
|
||||
size_t numBindings = global.bindings.len;
|
||||
ParserGlobalScopeData* data =
|
||||
NewEmptyGlobalScopeData(cx, alloc, numBindings);
|
||||
JS::Rooted<GlobalScope::Data*> data(
|
||||
cx, NewEmptyGlobalScopeData(cx, alloc, numBindings));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
@ -150,8 +150,8 @@ bool ConvertScopeStencil(JSContext* cx, const SmooshResult& result,
|
|||
|
||||
size_t numBindings = var.bindings.len;
|
||||
|
||||
ParserVarScopeData* data = NewEmptyVarScopeData(cx, alloc, numBindings);
|
||||
;
|
||||
JS::Rooted<VarScope::Data*> data(
|
||||
cx, NewEmptyVarScopeData(cx, alloc, numBindings));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
@ -177,8 +177,8 @@ bool ConvertScopeStencil(JSContext* cx, const SmooshResult& result,
|
|||
auto& lexical = scopeData.AsLexical();
|
||||
|
||||
size_t numBindings = lexical.bindings.len;
|
||||
ParserLexicalScopeData* data =
|
||||
NewEmptyLexicalScopeData(cx, alloc, numBindings);
|
||||
JS::Rooted<LexicalScope::Data*> data(
|
||||
cx, NewEmptyLexicalScopeData(cx, alloc, numBindings));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ bool ConvertScopeStencil(JSContext* cx, const SmooshResult& result,
|
|||
auto& function = scopeData.AsFunction();
|
||||
|
||||
size_t numBindings = function.bindings.len;
|
||||
ParserFunctionScopeData* data =
|
||||
NewEmptyFunctionScopeData(cx, alloc, numBindings);
|
||||
JS::Rooted<FunctionScope::Data*> data(
|
||||
cx, NewEmptyFunctionScopeData(cx, alloc, numBindings));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ UniquePtr<ImmutableScriptData> ConvertImmutableScriptData(
|
|||
// used by a script into ScriptThingsVector.
|
||||
bool ConvertGCThings(JSContext* cx, const SmooshResult& result,
|
||||
const SmooshScriptStencil& smooshStencil,
|
||||
Vector<const ParserAtom*>& allAtoms,
|
||||
JS::HandleVector<JSAtom*> allAtoms,
|
||||
MutableHandle<ScriptStencil> stencil) {
|
||||
auto& gcThings = stencil.get().gcThings;
|
||||
|
||||
|
@ -361,7 +361,8 @@ bool ConvertGCThings(JSContext* cx, const SmooshResult& result,
|
|||
break;
|
||||
}
|
||||
case SmooshGCThing::Tag::Atom: {
|
||||
gcThings.infallibleAppend(mozilla::AsVariant(allAtoms[item.AsAtom()]));
|
||||
gcThings.infallibleAppend(
|
||||
mozilla::AsVariant(allAtoms[item.AsAtom()].get()));
|
||||
break;
|
||||
}
|
||||
case SmooshGCThing::Tag::Function: {
|
||||
|
@ -392,7 +393,7 @@ bool ConvertGCThings(JSContext* cx, const SmooshResult& result,
|
|||
// (until GC things gets removed from stencil) tracing API of the GC.
|
||||
bool ConvertScriptStencil(JSContext* cx, const SmooshResult& result,
|
||||
const SmooshScriptStencil& smooshStencil,
|
||||
Vector<const ParserAtom*>& allAtoms,
|
||||
JS::HandleVector<JSAtom*> allAtoms,
|
||||
CompilationInfo& compilationInfo,
|
||||
MutableHandle<ScriptStencil> stencil) {
|
||||
using ImmutableFlags = js::ImmutableScriptFlagsEnum;
|
||||
|
@ -539,8 +540,8 @@ bool Smoosh::compileGlobalScriptToStencil(CompilationInfo& compilationInfo,
|
|||
|
||||
*unimplemented = false;
|
||||
|
||||
Vector<const ParserAtom*> allAtoms(cx);
|
||||
if (!ConvertAtoms(cx, result, compilationInfo, allAtoms)) {
|
||||
JS::RootedVector<JSAtom*> allAtoms(cx);
|
||||
if (!ConvertAtoms(cx, result, compilationInfo, &allAtoms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,6 @@ class FullParseHandler {
|
|||
* - lazyOuterFunction_ holds the lazyScript for this current parse
|
||||
* - lazyInnerFunctionIndex is used as we skip over inner functions
|
||||
* (see skipLazyInnerFunction),
|
||||
*
|
||||
* TODO-Stencil: We probably need to snapshot the atoms from the
|
||||
* lazyOuterFunction here.
|
||||
*/
|
||||
const Rooted<BaseScript*> lazyOuterFunction_;
|
||||
size_t lazyInnerFunctionIndex;
|
||||
|
@ -143,8 +140,7 @@ class FullParseHandler {
|
|||
// these assumptions.
|
||||
SourceKind sourceKind() const { return sourceKind_; }
|
||||
|
||||
NameNodeType newName(const ParserName* name, const TokenPos& pos,
|
||||
JSContext* cx) {
|
||||
NameNodeType newName(PropertyName* name, const TokenPos& pos, JSContext* cx) {
|
||||
return new_<NameNode>(ParseNodeKind::Name, name, pos);
|
||||
}
|
||||
|
||||
|
@ -153,12 +149,11 @@ class FullParseHandler {
|
|||
return new_<UnaryNode>(ParseNodeKind::ComputedName, pos, expr);
|
||||
}
|
||||
|
||||
NameNodeType newObjectLiteralPropertyName(const ParserAtom* atom,
|
||||
const TokenPos& pos) {
|
||||
NameNodeType newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
|
||||
return new_<NameNode>(ParseNodeKind::ObjectPropertyName, atom, pos);
|
||||
}
|
||||
|
||||
NameNodeType newPrivateName(const ParserAtom* atom, const TokenPos& pos) {
|
||||
NameNodeType newPrivateName(JSAtom* atom, const TokenPos& pos) {
|
||||
return new_<NameNode>(ParseNodeKind::PrivateName, atom, pos);
|
||||
}
|
||||
|
||||
|
@ -177,12 +172,11 @@ class FullParseHandler {
|
|||
return new_<BooleanLiteral>(cond, pos);
|
||||
}
|
||||
|
||||
NameNodeType newStringLiteral(const ParserAtom* atom, const TokenPos& pos) {
|
||||
NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) {
|
||||
return new_<NameNode>(ParseNodeKind::StringExpr, atom, pos);
|
||||
}
|
||||
|
||||
NameNodeType newTemplateStringLiteral(const ParserAtom* atom,
|
||||
const TokenPos& pos) {
|
||||
NameNodeType newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
|
||||
return new_<NameNode>(ParseNodeKind::TemplateStringExpr, atom, pos);
|
||||
}
|
||||
|
||||
|
@ -732,12 +726,12 @@ class FullParseHandler {
|
|||
return new_<CaseClause>(expr, body, begin);
|
||||
}
|
||||
|
||||
ContinueStatementType newContinueStatement(const ParserName* label,
|
||||
ContinueStatementType newContinueStatement(PropertyName* label,
|
||||
const TokenPos& pos) {
|
||||
return new_<ContinueStatement>(label, pos);
|
||||
}
|
||||
|
||||
BreakStatementType newBreakStatement(const ParserName* label,
|
||||
BreakStatementType newBreakStatement(PropertyName* label,
|
||||
const TokenPos& pos) {
|
||||
return new_<BreakStatement>(label, pos);
|
||||
}
|
||||
|
@ -757,7 +751,7 @@ class FullParseHandler {
|
|||
TokenPos(begin, body->pn_pos.end), expr, body);
|
||||
}
|
||||
|
||||
LabeledStatementType newLabeledStatement(const ParserName* label, Node stmt,
|
||||
LabeledStatementType newLabeledStatement(PropertyName* label, Node stmt,
|
||||
uint32_t begin) {
|
||||
return new_<LabeledStatement>(label, stmt, begin);
|
||||
}
|
||||
|
@ -777,7 +771,7 @@ class FullParseHandler {
|
|||
return new_<DebuggerStatement>(pos);
|
||||
}
|
||||
|
||||
NameNodeType newPropertyName(const ParserName* name, const TokenPos& pos) {
|
||||
NameNodeType newPropertyName(PropertyName* name, const TokenPos& pos) {
|
||||
return new_<NameNode>(ParseNodeKind::PropertyNameExpr, name, pos);
|
||||
}
|
||||
|
||||
|
@ -869,8 +863,7 @@ class FullParseHandler {
|
|||
return new_<ModuleNode>(pos);
|
||||
}
|
||||
|
||||
LexicalScopeNodeType newLexicalScope(ParserLexicalScopeData* bindings,
|
||||
Node body,
|
||||
LexicalScopeNodeType newLexicalScope(LexicalScope::Data* bindings, Node body,
|
||||
ScopeKind kind = ScopeKind::Lexical) {
|
||||
return new_<LexicalScopeNode>(bindings, body, kind);
|
||||
}
|
||||
|
@ -1061,14 +1054,14 @@ class FullParseHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
const ParserName* maybeDottedProperty(Node pn) {
|
||||
return pn->is<PropertyAccessBase>() ? pn->as<PropertyAccessBase>().name()
|
||||
PropertyName* maybeDottedProperty(Node pn) {
|
||||
return pn->is<PropertyAccessBase>() ? &pn->as<PropertyAccessBase>().name()
|
||||
: nullptr;
|
||||
}
|
||||
const ParserAtom* isStringExprStatement(Node pn, TokenPos* pos) {
|
||||
JSAtom* isStringExprStatement(Node pn, TokenPos* pos) {
|
||||
if (pn->is<UnaryNode>()) {
|
||||
UnaryNode* unary = &pn->as<UnaryNode>();
|
||||
if (const ParserAtom* atom = unary->isStringExprStatement()) {
|
||||
if (JSAtom* atom = unary->isStringExprStatement()) {
|
||||
*pos = unary->kid()->pn_pos;
|
||||
return atom;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ FunctionEmitter::FunctionEmitter(BytecodeEmitter* bce, FunctionBox* funbox,
|
|||
IsHoisted isHoisted)
|
||||
: bce_(bce),
|
||||
funbox_(funbox),
|
||||
name_(funbox_->explicitName()),
|
||||
name_(bce_->cx, funbox_->explicitName()),
|
||||
syntaxKind_(syntaxKind),
|
||||
isHoisted_(isHoisted) {}
|
||||
|
||||
|
@ -515,9 +515,8 @@ bool FunctionScriptEmitter::emitExtraBodyVarScope() {
|
|||
//
|
||||
// function f(x, y = 42) { var y; }
|
||||
//
|
||||
const ParserAtom* name = nullptr;
|
||||
for (ParserBindingIter bi(*funbox_->functionScopeBindings(), true); bi;
|
||||
bi++) {
|
||||
JS::Rooted<JSAtom*> name(bce_->cx);
|
||||
for (BindingIter bi(*funbox_->functionScopeBindings(), true); bi; bi++) {
|
||||
name = bi.name();
|
||||
|
||||
// There may not be a var binding of the same name.
|
||||
|
@ -699,7 +698,7 @@ bool FunctionScriptEmitter::emitEndBody() {
|
|||
bool FunctionScriptEmitter::intoStencil() {
|
||||
MOZ_ASSERT(state_ == State::EndBody);
|
||||
|
||||
if (!bce_->intoScriptStencil(&funbox_->functionStencil().get())) {
|
||||
if (!bce_->intoScriptStencil(funbox_->functionStencil().address())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -716,7 +715,7 @@ FunctionParamsEmitter::FunctionParamsEmitter(BytecodeEmitter* bce,
|
|||
funbox_(funbox),
|
||||
functionEmitterScope_(bce_->innermostEmitterScope()) {}
|
||||
|
||||
bool FunctionParamsEmitter::emitSimple(const ParserAtom* paramName) {
|
||||
bool FunctionParamsEmitter::emitSimple(JS::Handle<JSAtom*> paramName) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
|
||||
// [stack]
|
||||
|
@ -753,7 +752,7 @@ bool FunctionParamsEmitter::prepareForDefault() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FunctionParamsEmitter::emitDefaultEnd(const ParserAtom* paramName) {
|
||||
bool FunctionParamsEmitter::emitDefaultEnd(JS::Handle<JSAtom*> paramName) {
|
||||
MOZ_ASSERT(state_ == State::Default);
|
||||
|
||||
// [stack] DEFAULT
|
||||
|
@ -859,7 +858,7 @@ bool FunctionParamsEmitter::emitDestructuringDefaultEnd() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FunctionParamsEmitter::emitRest(const ParserAtom* paramName) {
|
||||
bool FunctionParamsEmitter::emitRest(JS::Handle<JSAtom*> paramName) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
|
||||
// [stack]
|
||||
|
@ -950,7 +949,7 @@ bool FunctionParamsEmitter::emitRestArray() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FunctionParamsEmitter::emitAssignment(const ParserAtom* paramName) {
|
||||
bool FunctionParamsEmitter::emitAssignment(JS::Handle<JSAtom*> paramName) {
|
||||
// [stack] ARG
|
||||
|
||||
NameLocation paramLoc =
|
||||
|
|
|
@ -72,7 +72,7 @@ class MOZ_STACK_CLASS FunctionEmitter {
|
|||
FunctionBox* funbox_;
|
||||
|
||||
// Function's explicit name.
|
||||
const ParserAtom* name_;
|
||||
JS::Rooted<JSAtom*> name_;
|
||||
|
||||
FunctionSyntaxKind syntaxKind_;
|
||||
IsHoisted isHoisted_;
|
||||
|
@ -410,10 +410,10 @@ class MOZ_STACK_CLASS FunctionParamsEmitter {
|
|||
|
||||
// paramName is used only when there's at least one expression in the
|
||||
// paramerters (funbox_->hasParameterExprs == true).
|
||||
MOZ_MUST_USE bool emitSimple(const ParserAtom* paramName);
|
||||
MOZ_MUST_USE bool emitSimple(JS::Handle<JSAtom*> paramName);
|
||||
|
||||
MOZ_MUST_USE bool prepareForDefault();
|
||||
MOZ_MUST_USE bool emitDefaultEnd(const ParserAtom* paramName);
|
||||
MOZ_MUST_USE bool emitDefaultEnd(JS::Handle<JSAtom*> paramName);
|
||||
|
||||
MOZ_MUST_USE bool prepareForDestructuring();
|
||||
MOZ_MUST_USE bool emitDestructuringEnd();
|
||||
|
@ -422,7 +422,7 @@ class MOZ_STACK_CLASS FunctionParamsEmitter {
|
|||
MOZ_MUST_USE bool prepareForDestructuringDefault();
|
||||
MOZ_MUST_USE bool emitDestructuringDefaultEnd();
|
||||
|
||||
MOZ_MUST_USE bool emitRest(const ParserAtom* paramName);
|
||||
MOZ_MUST_USE bool emitRest(JS::Handle<JSAtom*> paramName);
|
||||
|
||||
MOZ_MUST_USE bool prepareForDestructuringRest();
|
||||
MOZ_MUST_USE bool emitDestructuringRestEnd();
|
||||
|
@ -433,7 +433,7 @@ class MOZ_STACK_CLASS FunctionParamsEmitter {
|
|||
|
||||
MOZ_MUST_USE bool emitRestArray();
|
||||
|
||||
MOZ_MUST_USE bool emitAssignment(const ParserAtom* paramName);
|
||||
MOZ_MUST_USE bool emitAssignment(JS::Handle<JSAtom*> paramName);
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
void LabelEmitter::emitLabel(const ParserAtom* name) {
|
||||
void LabelEmitter::emitLabel(HandleAtom name) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
|
||||
controlInfo_.emplace(bce_, name, bce_->bytecodeSection().offset());
|
||||
|
|
|
@ -57,7 +57,7 @@ class MOZ_STACK_CLASS LabelEmitter {
|
|||
public:
|
||||
explicit LabelEmitter(BytecodeEmitter* bce) : bce_(bce) {}
|
||||
|
||||
void emitLabel(const ParserAtom* name);
|
||||
void emitLabel(HandleAtom name);
|
||||
MOZ_MUST_USE bool emitEnd();
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ using namespace js::frontend;
|
|||
LexicalScopeEmitter::LexicalScopeEmitter(BytecodeEmitter* bce) : bce_(bce) {}
|
||||
|
||||
bool LexicalScopeEmitter::emitScope(ScopeKind kind,
|
||||
ParserLexicalScopeData* bindings) {
|
||||
JS::Handle<LexicalScope::Data*> bindings) {
|
||||
MOZ_ASSERT(state_ == State::Start);
|
||||
MOZ_ASSERT(bindings);
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ class MOZ_STACK_CLASS LexicalScopeEmitter {
|
|||
// Returns the scope object for non-empty scope.
|
||||
const EmitterScope& emitterScope() const { return *emitterScope_; }
|
||||
|
||||
MOZ_MUST_USE bool emitScope(ScopeKind kind, ParserLexicalScopeData* bindings);
|
||||
MOZ_MUST_USE bool emitScope(ScopeKind kind,
|
||||
JS::Handle<LexicalScope::Data*> bindings);
|
||||
MOZ_MUST_USE bool emitEmptyScope();
|
||||
|
||||
MOZ_MUST_USE bool emitEnd();
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace frontend {
|
|||
|
||||
class MOZ_STACK_CLASS ModuleSharedContext : public SharedContext {
|
||||
public:
|
||||
ParserModuleScopeData* bindings;
|
||||
JS::Rooted<ModuleScope::Data*> bindings;
|
||||
ModuleBuilder& builder;
|
||||
|
||||
ModuleSharedContext(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <type_traits>
|
||||
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/Scope.h"
|
||||
|
||||
|
@ -354,7 +353,7 @@ class NameLocation {
|
|||
};
|
||||
|
||||
// These types are declared here for BaseScript::CreateLazy.
|
||||
using AtomVector = Vector<const ParserAtom*, 24, SystemAllocPolicy>;
|
||||
using AtomVector = Vector<JSAtom*, 24, SystemAllocPolicy>;
|
||||
|
||||
class FunctionBox;
|
||||
// FunctionBoxes stored in this type are required to be rooted
|
||||
|
|
|
@ -134,7 +134,7 @@ struct RecyclableAtomMapValueWrapper {
|
|||
const Wrapped* operator->() const { return &wrapped; }
|
||||
};
|
||||
|
||||
struct NameMapHasher : public DefaultHasher<const ParserAtom*> {
|
||||
struct NameMapHasher : public DefaultHasher<JSAtom*> {
|
||||
static inline HashNumber hash(const Lookup& l) {
|
||||
// Name maps use the atom's precomputed hash code, which is based on
|
||||
// the atom's contents rather than its pointer value. This is necessary
|
||||
|
@ -147,7 +147,7 @@ struct NameMapHasher : public DefaultHasher<const ParserAtom*> {
|
|||
|
||||
template <typename MapValue>
|
||||
using RecyclableNameMap =
|
||||
InlineMap<const ParserAtom*, RecyclableAtomMapValueWrapper<MapValue>, 24,
|
||||
InlineMap<JSAtom*, RecyclableAtomMapValueWrapper<MapValue>, 24,
|
||||
NameMapHasher, SystemAllocPolicy>;
|
||||
|
||||
using DeclaredNameMap = RecyclableNameMap<DeclaredNameInfo>;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/ParseNodeVisitor.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
@ -29,8 +28,7 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
|
||||
static const size_t MaxParents = 100;
|
||||
|
||||
CompilationInfo& compilationInfo_;
|
||||
const ParserAtom* prefix_;
|
||||
RootedAtom prefix_;
|
||||
|
||||
// Number of nodes in the parents array.
|
||||
size_t nparents_;
|
||||
|
@ -59,7 +57,7 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
* given code like a["b c"], the front end will produce a ParseNodeKind::Dot
|
||||
* with a ParseNodeKind::Name child whose name contains spaces.
|
||||
*/
|
||||
bool appendPropertyReference(const ParserAtom* name) {
|
||||
bool appendPropertyReference(JSAtom* name) {
|
||||
if (IsIdentifier(name)) {
|
||||
return buf_.append('.') && buf_.append(name);
|
||||
}
|
||||
|
@ -220,32 +218,31 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
* assign to the function's displayAtom field.
|
||||
*/
|
||||
MOZ_MUST_USE bool resolveFun(FunctionNode* funNode,
|
||||
const ParserAtom** retId) {
|
||||
MutableHandleAtom retAtom) {
|
||||
MOZ_ASSERT(funNode != nullptr);
|
||||
|
||||
FunctionBox* funbox = funNode->funbox();
|
||||
|
||||
MOZ_ASSERT(buf_.empty());
|
||||
auto resetBuf = mozilla::MakeScopeExit([&] { buf_.clear(); });
|
||||
|
||||
*retId = nullptr;
|
||||
retAtom.set(nullptr);
|
||||
|
||||
// If the function already has a name, use that.
|
||||
if (funbox->displayAtom()) {
|
||||
if (!prefix_) {
|
||||
*retId = funbox->displayAtom();
|
||||
if (funbox->displayAtom() != nullptr) {
|
||||
if (prefix_ == nullptr) {
|
||||
retAtom.set(funbox->displayAtom());
|
||||
return true;
|
||||
}
|
||||
if (!buf_.append(prefix_) || !buf_.append('/') ||
|
||||
!buf_.append(funbox->displayAtom())) {
|
||||
return false;
|
||||
}
|
||||
*retId = buf_.finishParserAtom(compilationInfo_);
|
||||
return !!*retId;
|
||||
retAtom.set(buf_.finishAtom());
|
||||
return !!retAtom;
|
||||
}
|
||||
|
||||
// If a prefix is specified, then it is a form of namespace.
|
||||
if (prefix_) {
|
||||
if (prefix_ != nullptr) {
|
||||
if (!buf_.append(prefix_) || !buf_.append('/')) {
|
||||
return false;
|
||||
}
|
||||
|
@ -315,15 +312,15 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
return true;
|
||||
}
|
||||
|
||||
*retId = buf_.finishParserAtom(compilationInfo_);
|
||||
if (!*retId) {
|
||||
retAtom.set(buf_.finishAtom());
|
||||
if (!retAtom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip assigning the guessed name if the function has a (dynamically)
|
||||
// computed inferred name.
|
||||
if (!funNode->isDirectRHSAnonFunction()) {
|
||||
funbox->setGuessedAtom(*retId);
|
||||
funbox->setGuessedAtom(retAtom);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -340,8 +337,8 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
|
||||
public:
|
||||
MOZ_MUST_USE bool visitFunction(FunctionNode* pn) {
|
||||
const ParserAtom* savedPrefix = prefix_;
|
||||
const ParserAtom* newPrefix = nullptr;
|
||||
RootedAtom savedPrefix(cx_, prefix_);
|
||||
RootedAtom newPrefix(cx_);
|
||||
if (!resolveFun(pn, &newPrefix)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -440,12 +437,8 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
return internalVisitSpecList(pn);
|
||||
}
|
||||
|
||||
explicit NameResolver(JSContext* cx, CompilationInfo& compilationInfo)
|
||||
: ParseNodeVisitor(cx),
|
||||
compilationInfo_(compilationInfo),
|
||||
prefix_(nullptr),
|
||||
nparents_(0),
|
||||
buf_(cx) {}
|
||||
explicit NameResolver(JSContext* cx)
|
||||
: ParseNodeVisitor(cx), prefix_(cx), nparents_(0), buf_(cx) {}
|
||||
|
||||
/*
|
||||
* Resolve names for all anonymous functions in the given ParseNode tree.
|
||||
|
@ -476,10 +469,9 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
|
|||
|
||||
} /* anonymous namespace */
|
||||
|
||||
bool frontend::NameFunctions(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
ParseNode* pn) {
|
||||
bool frontend::NameFunctions(JSContext* cx, ParseNode* pn) {
|
||||
AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx),
|
||||
TraceLogger_BytecodeNameFunctions);
|
||||
NameResolver nr(cx, compilationInfo);
|
||||
NameResolver nr(cx);
|
||||
return nr.visit(pn);
|
||||
}
|
||||
|
|
|
@ -15,10 +15,8 @@ namespace js {
|
|||
namespace frontend {
|
||||
|
||||
class ParseNode;
|
||||
struct CompilationInfo;
|
||||
|
||||
MOZ_MUST_USE bool NameFunctions(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
ParseNode* pn);
|
||||
MOZ_MUST_USE bool NameFunctions(JSContext* cx, ParseNode* pn);
|
||||
|
||||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name,
|
||||
Kind kind)
|
||||
: bce_(bce), kind_(kind), name_(name), loc_(bce_->lookupName(name_)) {}
|
||||
|
||||
NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name,
|
||||
const NameLocation& loc, Kind kind)
|
||||
: bce_(bce), kind_(kind), name_(name), loc_(loc) {}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class MOZ_STACK_CLASS NameOpEmitter {
|
|||
|
||||
bool emittedBindOp_ = false;
|
||||
|
||||
const ParserAtom* name_;
|
||||
Handle<JSAtom*> name_;
|
||||
|
||||
GCThingIndex atomIndex_;
|
||||
|
||||
|
@ -133,8 +133,8 @@ class MOZ_STACK_CLASS NameOpEmitter {
|
|||
#endif
|
||||
|
||||
public:
|
||||
NameOpEmitter(BytecodeEmitter* bce, const ParserAtom* name, Kind kind);
|
||||
NameOpEmitter(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name, Kind kind);
|
||||
NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name,
|
||||
const NameLocation& loc, Kind kind);
|
||||
|
||||
private:
|
||||
|
|
|
@ -6,11 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "frontend/ObjLiteral.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "frontend/CompilationInfo.h" // frontend::CompilationInfo
|
||||
#include "frontend/ParserAtom.h" // frontend::ParserAtom, frontend::ParserAtomTable
|
||||
#include "js/RootingAPI.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSObject.h"
|
||||
|
@ -24,47 +20,30 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
static bool InterpretObjLiteralValue(const ObjLiteralAtomVector& atoms,
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
const ObjLiteralInsn& insn,
|
||||
JS::Value* valOut) {
|
||||
static JS::Value InterpretObjLiteralValue(const ObjLiteralAtomVector& atoms,
|
||||
const ObjLiteralInsn& insn) {
|
||||
switch (insn.getOp()) {
|
||||
case ObjLiteralOpcode::ConstValue:
|
||||
*valOut = insn.getConstValue();
|
||||
return true;
|
||||
return insn.getConstValue();
|
||||
case ObjLiteralOpcode::ConstAtom: {
|
||||
uint32_t index = insn.getAtomIndex();
|
||||
// TODO-Stencil
|
||||
// This needs to be coalesced to wherever jsatom creation is eventually
|
||||
// Seems like InterpretLiteralObj would be called from main-thread
|
||||
// stencil instantiation.
|
||||
JSAtom* jsatom = compilationInfo.liftParserAtomToJSAtom(atoms[index]);
|
||||
if (!jsatom) {
|
||||
return false;
|
||||
}
|
||||
*valOut = StringValue(jsatom);
|
||||
return true;
|
||||
return StringValue(atoms[index]);
|
||||
}
|
||||
case ObjLiteralOpcode::Null:
|
||||
*valOut = NullValue();
|
||||
return true;
|
||||
return NullValue();
|
||||
case ObjLiteralOpcode::Undefined:
|
||||
*valOut = UndefinedValue();
|
||||
return true;
|
||||
return UndefinedValue();
|
||||
case ObjLiteralOpcode::True:
|
||||
*valOut = BooleanValue(true);
|
||||
return true;
|
||||
return BooleanValue(true);
|
||||
case ObjLiteralOpcode::False:
|
||||
*valOut = BooleanValue(false);
|
||||
return true;
|
||||
return BooleanValue(false);
|
||||
default:
|
||||
MOZ_CRASH("Unexpected object-literal instruction opcode");
|
||||
}
|
||||
}
|
||||
|
||||
static JSObject* InterpretObjLiteralObj(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
const ObjLiteralAtomVector& atoms,
|
||||
JSContext* cx, const ObjLiteralAtomVector& atoms,
|
||||
const mozilla::Span<const uint8_t> literalInsns, ObjLiteralFlags flags) {
|
||||
bool specificGroup = flags.contains(ObjLiteralFlag::SpecificGroup);
|
||||
bool singleton = flags.contains(ObjLiteralFlag::Singleton);
|
||||
|
@ -83,23 +62,12 @@ static JSObject* InterpretObjLiteralObj(
|
|||
if (insn.getKey().isArrayIndex()) {
|
||||
propId = INT_TO_JSID(insn.getKey().getArrayIndex());
|
||||
} else {
|
||||
// TODO-Stencil
|
||||
// Just a note, but it seems like this is an OK place to convert atoms
|
||||
// since the other GC allocations in the function (properties vector,
|
||||
// etc.) would need to be addressed.
|
||||
const frontend::ParserAtom* atom = atoms[insn.getKey().getAtomIndex()];
|
||||
JSAtom* jsatom = compilationInfo.liftParserAtomToJSAtom(atom);
|
||||
if (!jsatom) {
|
||||
return nullptr;
|
||||
}
|
||||
propId = AtomToId(compilationInfo.liftParserAtomToJSAtom(atom));
|
||||
propId = AtomToId(atoms[insn.getKey().getAtomIndex()]);
|
||||
}
|
||||
|
||||
JS::Value propVal;
|
||||
if (!noValues) {
|
||||
if (!InterpretObjLiteralValue(atoms, compilationInfo, insn, &propVal)) {
|
||||
return nullptr;
|
||||
}
|
||||
propVal = InterpretObjLiteralValue(atoms, insn);
|
||||
}
|
||||
|
||||
if (!properties.emplaceBack(propId, propVal)) {
|
||||
|
@ -118,8 +86,7 @@ static JSObject* InterpretObjLiteralObj(
|
|||
}
|
||||
|
||||
static JSObject* InterpretObjLiteralArray(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
const ObjLiteralAtomVector& atoms,
|
||||
JSContext* cx, const ObjLiteralAtomVector& atoms,
|
||||
const mozilla::Span<const uint8_t> literalInsns, ObjLiteralFlags flags) {
|
||||
bool isCow = flags.contains(ObjLiteralFlag::ArrayCOW);
|
||||
ObjLiteralReader reader(literalInsns);
|
||||
|
@ -130,10 +97,7 @@ static JSObject* InterpretObjLiteralArray(
|
|||
while (reader.readInsn(&insn)) {
|
||||
MOZ_ASSERT(insn.isValid());
|
||||
|
||||
JS::Value propVal;
|
||||
if (!InterpretObjLiteralValue(atoms, compilationInfo, insn, &propVal)) {
|
||||
return nullptr;
|
||||
}
|
||||
JS::Value propVal = InterpretObjLiteralValue(atoms, insn);
|
||||
if (!elements.append(propVal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -152,16 +116,12 @@ static JSObject* InterpretObjLiteralArray(
|
|||
return result;
|
||||
}
|
||||
|
||||
JSObject* InterpretObjLiteral(JSContext* cx,
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
const ObjLiteralAtomVector& atoms,
|
||||
JSObject* InterpretObjLiteral(JSContext* cx, const ObjLiteralAtomVector& atoms,
|
||||
const mozilla::Span<const uint8_t> literalInsns,
|
||||
ObjLiteralFlags flags) {
|
||||
return flags.contains(ObjLiteralFlag::Array)
|
||||
? InterpretObjLiteralArray(cx, compilationInfo, atoms,
|
||||
literalInsns, flags)
|
||||
: InterpretObjLiteralObj(cx, compilationInfo, atoms, literalInsns,
|
||||
flags);
|
||||
? InterpretObjLiteralArray(cx, atoms, literalInsns, flags)
|
||||
: InterpretObjLiteralObj(cx, atoms, literalInsns, flags);
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(JS_JITSPEW)
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/Span.h"
|
||||
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/GCPolicyAPI.h"
|
||||
#include "js/Value.h"
|
||||
|
@ -142,10 +141,6 @@ namespace js {
|
|||
|
||||
class JSONPrinter;
|
||||
|
||||
namespace frontend {
|
||||
struct CompilationInfo;
|
||||
}
|
||||
|
||||
// Object-literal instruction opcodes. An object literal is constructed by a
|
||||
// straight-line sequence of these ops, each adding one property to the
|
||||
// object.
|
||||
|
@ -549,20 +544,16 @@ struct ObjLiteralReader : private ObjLiteralReaderBase {
|
|||
}
|
||||
};
|
||||
|
||||
typedef Vector<const frontend::ParserAtom*, 4> ObjLiteralAtomVector;
|
||||
typedef Vector<JSAtom*, 4> ObjLiteralAtomVector;
|
||||
|
||||
JSObject* InterpretObjLiteral(JSContext* cx,
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
const ObjLiteralAtomVector& atoms,
|
||||
JSObject* InterpretObjLiteral(JSContext* cx, const ObjLiteralAtomVector& atoms,
|
||||
const mozilla::Span<const uint8_t> insns,
|
||||
ObjLiteralFlags flags);
|
||||
|
||||
inline JSObject* InterpretObjLiteral(JSContext* cx,
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
const ObjLiteralAtomVector& atoms,
|
||||
const ObjLiteralWriter& writer) {
|
||||
return InterpretObjLiteral(cx, compilationInfo, atoms, writer.getCode(),
|
||||
writer.getFlags());
|
||||
return InterpretObjLiteral(cx, atoms, writer.getCode(), writer.getFlags());
|
||||
}
|
||||
|
||||
class ObjLiteralStencil {
|
||||
|
@ -575,12 +566,12 @@ class ObjLiteralStencil {
|
|||
|
||||
ObjLiteralWriter& writer() { return writer_; }
|
||||
|
||||
bool addAtom(const frontend::ParserAtom* atom, uint32_t* index) {
|
||||
bool addAtom(JSAtom* atom, uint32_t* index) {
|
||||
*index = atoms_.length();
|
||||
return atoms_.append(atom);
|
||||
}
|
||||
|
||||
JSObject* create(JSContext* cx, frontend::CompilationInfo& info) const;
|
||||
JSObject* create(JSContext* cx) const;
|
||||
|
||||
#if defined(DEBUG) || defined(JS_JITSPEW)
|
||||
void dump();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "vm/NativeObject.h" // NativeDefineDataProperty
|
||||
#include "vm/ObjectGroup.h" // TenuredObject
|
||||
#include "vm/Opcodes.h" // JSOp
|
||||
#include "vm/Runtime.h" // cx->parserNames()
|
||||
#include "vm/Runtime.h" // JSAtomState (cx->parserNames())
|
||||
#include "vm/SharedStencil.h" // GCThingIndex
|
||||
|
||||
#include "gc/ObjectKind-inl.h" // GetGCObjectKind
|
||||
|
@ -263,8 +263,7 @@ bool PropertyEmitter::emitInitHomeObject() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PropertyEmitter::emitInit(AccessorType accessorType,
|
||||
const ParserAtom* key) {
|
||||
bool PropertyEmitter::emitInit(AccessorType accessorType, HandleAtom key) {
|
||||
switch (accessorType) {
|
||||
case AccessorType::None:
|
||||
return emitInit(isClass_ ? JSOp::InitHiddenProp : JSOp::InitProp, key);
|
||||
|
@ -295,7 +294,7 @@ bool PropertyEmitter::emitInitIndexOrComputed(AccessorType accessorType) {
|
|||
}
|
||||
}
|
||||
|
||||
bool PropertyEmitter::emitInit(JSOp op, const ParserAtom* key) {
|
||||
bool PropertyEmitter::emitInit(JSOp op, JS::Handle<JSAtom*> key) {
|
||||
MOZ_ASSERT(propertyState_ == PropertyState::PropValue ||
|
||||
propertyState_ == PropertyState::InitHomeObj);
|
||||
|
||||
|
@ -423,12 +422,12 @@ void AutoSaveLocalStrictMode::restore() {
|
|||
ClassEmitter::ClassEmitter(BytecodeEmitter* bce)
|
||||
: PropertyEmitter(bce),
|
||||
strictMode_(bce->sc),
|
||||
name_(nullptr),
|
||||
nameForAnonymousClass_(nullptr) {
|
||||
name_(bce->cx),
|
||||
nameForAnonymousClass_(bce->cx) {
|
||||
isClass_ = true;
|
||||
}
|
||||
|
||||
bool ClassEmitter::emitScope(ParserLexicalScopeData* scopeBindings) {
|
||||
bool ClassEmitter::emitScope(JS::Handle<LexicalScope::Data*> scopeBindings) {
|
||||
MOZ_ASSERT(propertyState_ == PropertyState::Start);
|
||||
MOZ_ASSERT(classState_ == ClassState::Start);
|
||||
|
||||
|
@ -446,7 +445,8 @@ bool ClassEmitter::emitScope(ParserLexicalScopeData* scopeBindings) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ClassEmitter::emitBodyScope(ParserLexicalScopeData* scopeBindings) {
|
||||
bool ClassEmitter::emitBodyScope(
|
||||
JS::Handle<LexicalScope::Data*> scopeBindings) {
|
||||
MOZ_ASSERT(propertyState_ == PropertyState::Start);
|
||||
MOZ_ASSERT(classState_ == ClassState::Start ||
|
||||
classState_ == ClassState::Scope);
|
||||
|
@ -465,8 +465,8 @@ bool ClassEmitter::emitBodyScope(ParserLexicalScopeData* scopeBindings) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ClassEmitter::emitClass(const ParserAtom* name,
|
||||
const ParserAtom* nameForAnonymousClass,
|
||||
bool ClassEmitter::emitClass(JS::Handle<JSAtom*> name,
|
||||
JS::Handle<JSAtom*> nameForAnonymousClass,
|
||||
bool hasNameOnStack) {
|
||||
MOZ_ASSERT(propertyState_ == PropertyState::Start);
|
||||
MOZ_ASSERT(classState_ == ClassState::Start ||
|
||||
|
@ -493,8 +493,8 @@ bool ClassEmitter::emitClass(const ParserAtom* name,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ClassEmitter::emitDerivedClass(const ParserAtom* name,
|
||||
const ParserAtom* nameForAnonymousClass,
|
||||
bool ClassEmitter::emitDerivedClass(JS::Handle<JSAtom*> name,
|
||||
JS::Handle<JSAtom*> nameForAnonymousClass,
|
||||
bool hasNameOnStack) {
|
||||
MOZ_ASSERT(propertyState_ == PropertyState::Start);
|
||||
MOZ_ASSERT(classState_ == ClassState::Start ||
|
||||
|
@ -616,7 +616,7 @@ bool ClassEmitter::emitInitDefaultConstructor(uint32_t classStart,
|
|||
MOZ_ASSERT(propertyState_ == PropertyState::Start);
|
||||
MOZ_ASSERT(classState_ == ClassState::Class);
|
||||
|
||||
const ParserAtom* className = name_;
|
||||
RootedAtom className(bce_->cx, name_);
|
||||
if (!className) {
|
||||
if (nameForAnonymousClass_) {
|
||||
className = nameForAnonymousClass_;
|
||||
|
@ -707,9 +707,9 @@ bool ClassEmitter::prepareForMemberInitializers(size_t numInitializers,
|
|||
// .initializers is a variable that stores an array of lambdas containing
|
||||
// code (the initializer) for each field. Upon an object's construction,
|
||||
// these lambdas will be called, defining the values.
|
||||
const ParserName* initializers =
|
||||
isStatic ? bce_->cx->parserNames().dotStaticInitializers
|
||||
: bce_->cx->parserNames().dotInitializers;
|
||||
auto initializersName = isStatic ? &JSAtomState::dotStaticInitializers
|
||||
: &JSAtomState::dotInitializers;
|
||||
HandlePropertyName initializers = bce_->cx->parserNames().*initializersName;
|
||||
initializersAssignment_.emplace(bce_, initializers,
|
||||
NameOpEmitter::Kind::Initialize);
|
||||
if (!initializersAssignment_->prepareForRhs()) {
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
#include "frontend/NameOpEmitter.h" // NameOpEmitter
|
||||
#include "frontend/ParseNode.h" // AccessorType
|
||||
#include "frontend/TDZCheckCache.h" // TDZCheckCache
|
||||
#include "js/RootingAPI.h" // JS::Handle, JS::Rooted
|
||||
#include "vm/BytecodeUtil.h" // JSOp
|
||||
#include "vm/JSAtom.h" // JSAtom
|
||||
#include "vm/NativeObject.h" // PlainObject
|
||||
#include "vm/Scope.h" // LexicalScope
|
||||
|
||||
|
@ -233,7 +235,7 @@ class MOZ_STACK_CLASS PropertyEmitter {
|
|||
|
||||
// @param key
|
||||
// Property key
|
||||
MOZ_MUST_USE bool emitInit(AccessorType accessorType, const ParserAtom* key);
|
||||
MOZ_MUST_USE bool emitInit(AccessorType accessorType, HandleAtom key);
|
||||
|
||||
MOZ_MUST_USE bool emitInitIndexOrComputed(AccessorType accessorType);
|
||||
|
||||
|
@ -245,7 +247,7 @@ class MOZ_STACK_CLASS PropertyEmitter {
|
|||
// Opcode for initializing property
|
||||
// @param key
|
||||
// Atom of the property if the property key is not computed
|
||||
MOZ_MUST_USE bool emitInit(JSOp op, const ParserAtom* key);
|
||||
MOZ_MUST_USE bool emitInit(JSOp op, JS::Handle<JSAtom*> key);
|
||||
MOZ_MUST_USE bool emitInitIndexOrComputed(JSOp op);
|
||||
|
||||
MOZ_MUST_USE bool emitPopClassConstructor();
|
||||
|
@ -753,8 +755,8 @@ class MOZ_STACK_CLASS ClassEmitter : public PropertyEmitter {
|
|||
size_t numInitializers_ = 0;
|
||||
#endif
|
||||
|
||||
const ParserAtom* name_;
|
||||
const ParserAtom* nameForAnonymousClass_;
|
||||
JS::Rooted<JSAtom*> name_;
|
||||
JS::Rooted<JSAtom*> nameForAnonymousClass_;
|
||||
bool hasNameOnStack_ = false;
|
||||
mozilla::Maybe<NameOpEmitter> initializersAssignment_;
|
||||
size_t initializerIndex_ = 0;
|
||||
|
@ -762,8 +764,9 @@ class MOZ_STACK_CLASS ClassEmitter : public PropertyEmitter {
|
|||
public:
|
||||
explicit ClassEmitter(BytecodeEmitter* bce);
|
||||
|
||||
bool emitScope(ParserLexicalScopeData* scopeBindings);
|
||||
bool emitBodyScope(ParserLexicalScopeData* scopeBindings);
|
||||
bool emitScope(JS::Handle<LexicalScope::Data*> scopeBindings);
|
||||
|
||||
bool emitBodyScope(JS::Handle<LexicalScope::Data*> scopeBindings);
|
||||
|
||||
// @param name
|
||||
// Name of the class (nullptr if this is anonymous class)
|
||||
|
@ -771,11 +774,11 @@ class MOZ_STACK_CLASS ClassEmitter : public PropertyEmitter {
|
|||
// Statically inferred name of the class (only for anonymous classes)
|
||||
// @param hasNameOnStack
|
||||
// If true the name is on the stack (only for anonymous classes)
|
||||
MOZ_MUST_USE bool emitClass(const ParserAtom* name,
|
||||
const ParserAtom* nameForAnonymousClass,
|
||||
MOZ_MUST_USE bool emitClass(JS::Handle<JSAtom*> name,
|
||||
JS::Handle<JSAtom*> nameForAnonymousClass,
|
||||
bool hasNameOnStack);
|
||||
MOZ_MUST_USE bool emitDerivedClass(const ParserAtom* name,
|
||||
const ParserAtom* nameForAnonymousClass,
|
||||
MOZ_MUST_USE bool emitDerivedClass(JS::Handle<JSAtom*> name,
|
||||
JS::Handle<JSAtom*> nameForAnonymousClass,
|
||||
bool hasNameOnStack);
|
||||
|
||||
// @param needsHomeObject
|
||||
|
|
|
@ -63,7 +63,7 @@ inline ParseContext::VarScope::VarScope(JSContext* cx, ParseContext* pc,
|
|||
}
|
||||
|
||||
inline JS::Result<Ok, ParseContext::BreakStatementError>
|
||||
ParseContext::checkBreakStatement(const ParserName* label) {
|
||||
ParseContext::checkBreakStatement(PropertyName* label) {
|
||||
// Labeled 'break' statements target the nearest labeled statements (could
|
||||
// be any kind) with the same label. Unlabeled 'break' statements target
|
||||
// the innermost loop or switch statement.
|
||||
|
@ -91,7 +91,7 @@ ParseContext::checkBreakStatement(const ParserName* label) {
|
|||
}
|
||||
|
||||
inline JS::Result<Ok, ParseContext::ContinueStatementError>
|
||||
ParseContext::checkContinueStatement(const ParserName* label) {
|
||||
ParseContext::checkContinueStatement(PropertyName* label) {
|
||||
// Labeled 'continue' statements target the nearest labeled loop
|
||||
// statements with the same label. Unlabeled 'continue' statements target
|
||||
// the innermost loop statement.
|
||||
|
|
|
@ -62,7 +62,7 @@ bool DeclarationKindIsParameter(DeclarationKind kind) {
|
|||
kind == DeclarationKind::FormalParameter;
|
||||
}
|
||||
|
||||
bool UsedNameTracker::noteUse(JSContext* cx, const ParserAtom* name,
|
||||
bool UsedNameTracker::noteUse(JSContext* cx, JSAtom* name,
|
||||
NameVisibility visibility, uint32_t scriptId,
|
||||
uint32_t scopeId,
|
||||
mozilla::Maybe<TokenPos> tokenPosition) {
|
||||
|
@ -161,7 +161,7 @@ void ParseContext::Scope::dump(ParseContext* pc) {
|
|||
|
||||
fprintf(stdout, "\n decls:\n");
|
||||
for (DeclaredNameMap::Range r = declared_->all(); !r.empty(); r.popFront()) {
|
||||
UniqueChars bytes = QuoteString(cx, r.front().key());
|
||||
UniqueChars bytes = AtomToPrintableString(cx, r.front().key());
|
||||
if (!bytes) {
|
||||
return;
|
||||
}
|
||||
|
@ -195,11 +195,12 @@ bool ParseContext::Scope::propagateAndMarkAnnexBFunctionBoxes(
|
|||
if (this == &pc->varScope()) {
|
||||
// Base case: actually declare the Annex B vars and mark applicable
|
||||
// function boxes as Annex B.
|
||||
RootedPropertyName name(pc->sc()->cx_);
|
||||
Maybe<DeclarationKind> redeclaredKind;
|
||||
uint32_t unused;
|
||||
for (FunctionBox* funbox : *possibleAnnexBFunctionBoxes_) {
|
||||
if (pc->annexBAppliesToLexicalFunctionInInnermostScope(funbox)) {
|
||||
const ParserName* name = funbox->explicitName()->asName();
|
||||
name = funbox->explicitName()->asPropertyName();
|
||||
if (!pc->tryDeclareVar(
|
||||
name, DeclarationKind::VarForAnnexBLexicalFunction,
|
||||
DeclaredNameInfo::npos, &redeclaredKind, &unused)) {
|
||||
|
@ -241,7 +242,7 @@ bool ParseContext::Scope::addCatchParameters(ParseContext* pc,
|
|||
DeclarationKind kind = r.front().value()->kind();
|
||||
uint32_t pos = r.front().value()->pos();
|
||||
MOZ_ASSERT(DeclarationKindIsCatchParameter(kind));
|
||||
const ParserAtom* name = r.front().key();
|
||||
JSAtom* name = r.front().key();
|
||||
AddDeclaredNamePtr p = lookupDeclaredNameForAdd(name);
|
||||
MOZ_ASSERT(!p);
|
||||
if (!addDeclaredName(pc, p, name, kind, pos)) {
|
||||
|
@ -347,7 +348,7 @@ bool ParseContext::annexBAppliesToLexicalFunctionInInnermostScope(
|
|||
FunctionBox* funbox) {
|
||||
MOZ_ASSERT(!sc()->strict());
|
||||
|
||||
const ParserName* name = funbox->explicitName()->asName();
|
||||
RootedPropertyName name(sc()->cx_, funbox->explicitName()->asPropertyName());
|
||||
Maybe<DeclarationKind> redeclaredKind = isVarRedeclaredInInnermostScope(
|
||||
name, DeclarationKind::VarForAnnexBLexicalFunction);
|
||||
|
||||
|
@ -376,7 +377,7 @@ bool ParseContext::annexBAppliesToLexicalFunctionInInnermostScope(
|
|||
}
|
||||
|
||||
Maybe<DeclarationKind> ParseContext::isVarRedeclaredInInnermostScope(
|
||||
const ParserName* name, DeclarationKind kind) {
|
||||
HandlePropertyName name, DeclarationKind kind) {
|
||||
Maybe<DeclarationKind> redeclaredKind;
|
||||
uint32_t unused;
|
||||
MOZ_ALWAYS_TRUE(tryDeclareVarHelper<DryRunInnermostScopeOnly>(
|
||||
|
@ -384,20 +385,11 @@ Maybe<DeclarationKind> ParseContext::isVarRedeclaredInInnermostScope(
|
|||
return redeclaredKind;
|
||||
}
|
||||
|
||||
bool ParseContext::isVarRedeclaredInEval(const ParserName* name,
|
||||
DeclarationKind kind,
|
||||
Maybe<DeclarationKind>* out) {
|
||||
MOZ_ASSERT(out);
|
||||
Maybe<DeclarationKind> ParseContext::isVarRedeclaredInEval(
|
||||
HandlePropertyName name, DeclarationKind kind) {
|
||||
MOZ_ASSERT(DeclarationKindIsVar(kind));
|
||||
MOZ_ASSERT(sc()->isEvalContext());
|
||||
|
||||
// TODO-Stencil: After scope snapshotting, this can be done away with.
|
||||
auto mbNameAtom = name->toJSAtom(sc()->cx_);
|
||||
if (mbNameAtom.isErr()) {
|
||||
return false;
|
||||
}
|
||||
JSAtom* nameAtom = mbNameAtom.unwrap();
|
||||
|
||||
// In the case of eval, we also need to check enclosing VM scopes to see
|
||||
// if the var declaration is allowed in the context.
|
||||
js::Scope* enclosingScope = sc()->compilationInfo().enclosingScope;
|
||||
|
@ -405,7 +397,7 @@ bool ParseContext::isVarRedeclaredInEval(const ParserName* name,
|
|||
MOZ_ASSERT(varScope);
|
||||
for (ScopeIter si(enclosingScope); si; si++) {
|
||||
for (js::BindingIter bi(si.scope()); bi; bi++) {
|
||||
if (bi.name() != nameAtom) {
|
||||
if (bi.name() != name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -415,17 +407,15 @@ bool ParseContext::isVarRedeclaredInEval(const ParserName* name,
|
|||
// catch parameters with var declarations.
|
||||
bool annexB35Allowance = si.kind() == ScopeKind::SimpleCatch;
|
||||
if (!annexB35Allowance) {
|
||||
*out = Some(ScopeKindIsCatch(si.kind())
|
||||
return Some(ScopeKindIsCatch(si.kind())
|
||||
? DeclarationKind::CatchParameter
|
||||
: DeclarationKind::Let);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BindingKind::Const:
|
||||
*out = Some(DeclarationKind::Const);
|
||||
return true;
|
||||
return Some(DeclarationKind::Const);
|
||||
|
||||
case BindingKind::Import:
|
||||
case BindingKind::FormalParameter:
|
||||
|
@ -440,11 +430,10 @@ bool ParseContext::isVarRedeclaredInEval(const ParserName* name,
|
|||
}
|
||||
}
|
||||
|
||||
*out = Nothing();
|
||||
return true;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool ParseContext::tryDeclareVar(const ParserName* name, DeclarationKind kind,
|
||||
bool ParseContext::tryDeclareVar(HandlePropertyName name, DeclarationKind kind,
|
||||
uint32_t beginPos,
|
||||
Maybe<DeclarationKind>* redeclaredKind,
|
||||
uint32_t* prevPos) {
|
||||
|
@ -453,7 +442,7 @@ bool ParseContext::tryDeclareVar(const ParserName* name, DeclarationKind kind,
|
|||
}
|
||||
|
||||
template <ParseContext::DryRunOption dryRunOption>
|
||||
bool ParseContext::tryDeclareVarHelper(const ParserName* name,
|
||||
bool ParseContext::tryDeclareVarHelper(HandlePropertyName name,
|
||||
DeclarationKind kind, uint32_t beginPos,
|
||||
Maybe<DeclarationKind>* redeclaredKind,
|
||||
uint32_t* prevPos) {
|
||||
|
@ -523,9 +512,7 @@ bool ParseContext::tryDeclareVarHelper(const ParserName* name,
|
|||
|
||||
if (!sc()->strict() && sc()->isEvalContext() &&
|
||||
(dryRunOption == NotDryRun || innermostScope() == &varScope())) {
|
||||
if (!isVarRedeclaredInEval(name, kind, redeclaredKind)) {
|
||||
return false;
|
||||
}
|
||||
*redeclaredKind = isVarRedeclaredInEval(name, kind);
|
||||
// We don't have position information at runtime.
|
||||
*prevPos = DeclaredNameInfo::npos;
|
||||
}
|
||||
|
@ -534,7 +521,7 @@ bool ParseContext::tryDeclareVarHelper(const ParserName* name,
|
|||
}
|
||||
|
||||
bool ParseContext::hasUsedName(const UsedNameTracker& usedNames,
|
||||
const ParserName* name) {
|
||||
HandlePropertyName name) {
|
||||
if (auto p = usedNames.lookup(name)) {
|
||||
return p->value().isUsedInScript(scriptId());
|
||||
}
|
||||
|
@ -542,7 +529,7 @@ bool ParseContext::hasUsedName(const UsedNameTracker& usedNames,
|
|||
}
|
||||
|
||||
bool ParseContext::hasUsedFunctionSpecialName(const UsedNameTracker& usedNames,
|
||||
const ParserName* name) {
|
||||
HandlePropertyName name) {
|
||||
MOZ_ASSERT(name == sc()->cx_->parserNames().arguments ||
|
||||
name == sc()->cx_->parserNames().dotThis);
|
||||
return hasUsedName(usedNames, name) ||
|
||||
|
@ -560,7 +547,7 @@ bool ParseContext::declareFunctionThis(const UsedNameTracker& usedNames,
|
|||
// Derived class constructors emit JSOp::CheckReturn, which requires
|
||||
// '.this' to be bound.
|
||||
FunctionBox* funbox = functionBox();
|
||||
const ParserName* dotThis = sc()->cx_->parserNames().dotThis;
|
||||
HandlePropertyName dotThis = sc()->cx_->parserNames().dotThis;
|
||||
|
||||
bool declareThis;
|
||||
if (canSkipLazyClosedOverBindings) {
|
||||
|
@ -594,7 +581,7 @@ bool ParseContext::declareFunctionArgumentsObject(
|
|||
bool hasExtraBodyVarScope = &funScope != &_varScope;
|
||||
|
||||
// Time to implement the odd semantics of 'arguments'.
|
||||
const ParserName* argumentsName = sc()->cx_->parserNames().arguments;
|
||||
HandlePropertyName argumentsName = sc()->cx_->parserNames().arguments;
|
||||
|
||||
bool tryDeclareArguments;
|
||||
if (canSkipLazyClosedOverBindings) {
|
||||
|
@ -658,7 +645,7 @@ bool ParseContext::declareDotGeneratorName() {
|
|||
// The special '.generator' binding must be on the function scope, as
|
||||
// generators expect to find it on the CallObject.
|
||||
ParseContext::Scope& funScope = functionScope();
|
||||
const ParserName* dotGenerator = sc()->cx_->parserNames().dotGenerator;
|
||||
HandlePropertyName dotGenerator = sc()->cx_->parserNames().dotGenerator;
|
||||
AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotGenerator);
|
||||
if (!p &&
|
||||
!funScope.addDeclaredName(this, p, dotGenerator, DeclarationKind::Var,
|
||||
|
|
|
@ -69,13 +69,13 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
};
|
||||
|
||||
class LabelStatement : public Statement {
|
||||
const ParserAtom* label_;
|
||||
RootedAtom label_;
|
||||
|
||||
public:
|
||||
LabelStatement(ParseContext* pc, const ParserAtom* label)
|
||||
: Statement(pc, StatementKind::Label), label_(label) {}
|
||||
LabelStatement(ParseContext* pc, JSAtom* label)
|
||||
: Statement(pc, StatementKind::Label), label_(pc->sc_->cx_, label) {}
|
||||
|
||||
const ParserAtom* label() const { return label_; }
|
||||
HandleAtom label() const { return label_; }
|
||||
};
|
||||
|
||||
struct ClassStatement : public Statement {
|
||||
|
@ -140,17 +140,17 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
|
||||
bool isEmpty() const { return declared_->all().empty(); }
|
||||
|
||||
DeclaredNamePtr lookupDeclaredName(const ParserAtom* name) {
|
||||
DeclaredNamePtr lookupDeclaredName(JSAtom* name) {
|
||||
return declared_->lookup(name);
|
||||
}
|
||||
|
||||
AddDeclaredNamePtr lookupDeclaredNameForAdd(const ParserAtom* name) {
|
||||
AddDeclaredNamePtr lookupDeclaredNameForAdd(JSAtom* name) {
|
||||
return declared_->lookupForAdd(name);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addDeclaredName(ParseContext* pc, AddDeclaredNamePtr& p,
|
||||
const ParserAtom* name,
|
||||
DeclarationKind kind, uint32_t pos) {
|
||||
JSAtom* name, DeclarationKind kind,
|
||||
uint32_t pos) {
|
||||
return maybeReportOOM(
|
||||
pc, declared_->add(p, name, DeclaredNameInfo(kind, pos)));
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
|
||||
explicit operator bool() const { return !done(); }
|
||||
|
||||
const ParserAtom* name() {
|
||||
JSAtom* name() {
|
||||
MOZ_ASSERT(!done());
|
||||
return declaredRange_.front().key();
|
||||
}
|
||||
|
@ -402,14 +402,14 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
// Return Err(true) if we have encountered at least one loop,
|
||||
// Err(false) otherwise.
|
||||
MOZ_MUST_USE inline JS::Result<Ok, BreakStatementError> checkBreakStatement(
|
||||
const ParserName* label);
|
||||
PropertyName* label);
|
||||
|
||||
enum class ContinueStatementError {
|
||||
NotInALoop,
|
||||
LabelNotFound,
|
||||
};
|
||||
MOZ_MUST_USE inline JS::Result<Ok, ContinueStatementError>
|
||||
checkContinueStatement(const ParserName* label);
|
||||
checkContinueStatement(PropertyName* label);
|
||||
|
||||
// True if we are at the topmost level of a entire script or function body.
|
||||
// For example, while parsing this code we would encounter f1 and f2 at
|
||||
|
@ -480,14 +480,14 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
|
||||
bool annexBAppliesToLexicalFunctionInInnermostScope(FunctionBox* funbox);
|
||||
|
||||
bool tryDeclareVar(const ParserName* name, DeclarationKind kind,
|
||||
bool tryDeclareVar(HandlePropertyName name, DeclarationKind kind,
|
||||
uint32_t beginPos,
|
||||
mozilla::Maybe<DeclarationKind>* redeclaredKind,
|
||||
uint32_t* prevPos);
|
||||
|
||||
bool hasUsedName(const UsedNameTracker& usedNames, const ParserName* name);
|
||||
bool hasUsedName(const UsedNameTracker& usedNames, HandlePropertyName name);
|
||||
bool hasUsedFunctionSpecialName(const UsedNameTracker& usedNames,
|
||||
const ParserName* name);
|
||||
HandlePropertyName name);
|
||||
|
||||
bool declareFunctionThis(const UsedNameTracker& usedNames,
|
||||
bool canSkipLazyClosedOverBindings);
|
||||
|
@ -497,15 +497,13 @@ class ParseContext : public Nestable<ParseContext> {
|
|||
|
||||
private:
|
||||
mozilla::Maybe<DeclarationKind> isVarRedeclaredInInnermostScope(
|
||||
const ParserName* name, DeclarationKind kind);
|
||||
|
||||
MOZ_MUST_USE bool isVarRedeclaredInEval(const ParserName* name,
|
||||
DeclarationKind kind,
|
||||
mozilla::Maybe<DeclarationKind>* out);
|
||||
HandlePropertyName name, DeclarationKind kind);
|
||||
mozilla::Maybe<DeclarationKind> isVarRedeclaredInEval(HandlePropertyName name,
|
||||
DeclarationKind kind);
|
||||
|
||||
enum DryRunOption { NotDryRun, DryRunInnermostScopeOnly };
|
||||
template <DryRunOption dryRunOption>
|
||||
bool tryDeclareVarHelper(const ParserName* name, DeclarationKind kind,
|
||||
bool tryDeclareVarHelper(HandlePropertyName name, DeclarationKind kind,
|
||||
uint32_t beginPos,
|
||||
mozilla::Maybe<DeclarationKind>* redeclaredKind,
|
||||
uint32_t* prevPos);
|
||||
|
|
|
@ -199,23 +199,12 @@ void RegExpLiteral::dumpImpl(GenericPrinter& out, int indent) {
|
|||
out.printf("(%s)", parseNodeNames[getKindAsIndex()]);
|
||||
}
|
||||
|
||||
static void DumpCharsNoNewline(const ParserAtom* atom,
|
||||
js::GenericPrinter& out) {
|
||||
if (atom->hasLatin1Chars()) {
|
||||
out.put("[Latin 1]");
|
||||
JSString::dumpChars(atom->latin1Chars(), atom->length(), out);
|
||||
} else {
|
||||
out.put("[2 byte]");
|
||||
JSString::dumpChars(atom->twoByteChars(), atom->length(), out);
|
||||
}
|
||||
}
|
||||
|
||||
void LoopControlStatement::dumpImpl(GenericPrinter& out, int indent) {
|
||||
const char* name = parseNodeNames[getKindAsIndex()];
|
||||
out.printf("(%s", name);
|
||||
if (label()) {
|
||||
out.printf(" ");
|
||||
DumpCharsNoNewline(label(), out);
|
||||
label()->dumpCharsNoNewline(out);
|
||||
}
|
||||
out.printf(")");
|
||||
}
|
||||
|
@ -319,7 +308,7 @@ void NameNode::dumpImpl(GenericPrinter& out, int indent) {
|
|||
case ParseNodeKind::StringExpr:
|
||||
case ParseNodeKind::TemplateStringExpr:
|
||||
case ParseNodeKind::ObjectPropertyName:
|
||||
DumpCharsNoNewline(atom(), out);
|
||||
atom()->dumpCharsNoNewline(out);
|
||||
return;
|
||||
|
||||
case ParseNodeKind::Name:
|
||||
|
@ -329,10 +318,11 @@ void NameNode::dumpImpl(GenericPrinter& out, int indent) {
|
|||
if (!atom()) {
|
||||
out.put("#<null name>");
|
||||
} else {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (atom()->hasLatin1Chars()) {
|
||||
DumpName(out, atom()->latin1Chars(), atom()->length());
|
||||
DumpName(out, atom()->latin1Chars(nogc), atom()->length());
|
||||
} else {
|
||||
DumpName(out, atom()->twoByteChars(), atom()->length());
|
||||
DumpName(out, atom()->twoByteChars(nogc), atom()->length());
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -353,7 +343,7 @@ void NameNode::dumpImpl(GenericPrinter& out, int indent) {
|
|||
void LabeledStatement::dumpImpl(GenericPrinter& out, int indent) {
|
||||
const char* name = parseNodeNames[getKindAsIndex()];
|
||||
out.printf("(%s ", name);
|
||||
DumpCharsNoNewline(atom(), out);
|
||||
atom()->dumpCharsNoNewline(out);
|
||||
out.printf(" ");
|
||||
indent += strlen(name) + atom()->length() + 3;
|
||||
DumpParseTree(statement(), out, indent);
|
||||
|
@ -365,13 +355,14 @@ void LexicalScopeNode::dumpImpl(GenericPrinter& out, int indent) {
|
|||
out.printf("(%s [", name);
|
||||
int nameIndent = indent + strlen(name) + 3;
|
||||
if (!isEmptyScope()) {
|
||||
ParserScopeData<LexicalScope>* bindings = scopeBindings();
|
||||
LexicalScope::Data* bindings = scopeBindings();
|
||||
for (uint32_t i = 0; i < bindings->length; i++) {
|
||||
const ParserAtom* name = bindings->trailingNames[i].name();
|
||||
JSAtom* name = bindings->trailingNames[i].name();
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (name->hasLatin1Chars()) {
|
||||
DumpName(out, name->latin1Chars(), name->length());
|
||||
DumpName(out, name->latin1Chars(nogc), name->length());
|
||||
} else {
|
||||
DumpName(out, name->twoByteChars(), name->length());
|
||||
DumpName(out, name->twoByteChars(nogc), name->length());
|
||||
}
|
||||
if (i < bindings->length - 1) {
|
||||
IndentNewLine(out, nameIndent);
|
||||
|
@ -394,9 +385,8 @@ bool BigIntLiteral::isZero() {
|
|||
return compilationInfo_.bigIntData[index_].isZero();
|
||||
}
|
||||
|
||||
const ParserAtom* NumericLiteral::toAtom(
|
||||
CompilationInfo& compilationInfo) const {
|
||||
return NumberToParserAtom(compilationInfo, value());
|
||||
JSAtom* NumericLiteral::toAtom(JSContext* cx) const {
|
||||
return NumberToAtom(cx, value());
|
||||
}
|
||||
|
||||
RegExpObject* RegExpStencil::createRegExp(JSContext* cx) const {
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
|
||||
#include "frontend/NameAnalysisTypes.h" // PrivateNameKind
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "frontend/Stencil.h"
|
||||
#include "frontend/Token.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
@ -39,9 +38,16 @@
|
|||
//
|
||||
// - This bulk-deallocation DOES NOT run destructors.
|
||||
//
|
||||
// - Instances of `ParserScopeData<LexicalScope>` MUST BE allocated as
|
||||
// instances of `ParseNode`, in the same `LifoAlloc`. They are bulk-
|
||||
// deallocated alongside the rest of the tree.
|
||||
// - Instances of `LexicalScope::Data` MUST BE allocated as instances of
|
||||
// `ParseNode`, in the same `LifoAlloc`. They are bulk-deallocated alongside
|
||||
// the rest of the tree.
|
||||
//
|
||||
// - Instances of `JSAtom` used throughout the tree (including instances of
|
||||
// `PropertyName`) MUST be kept alive by the parser. This is done through an
|
||||
// instance of `AutoKeepAtoms` held by the parser.
|
||||
//
|
||||
// - Once the parser is deallocated, the `JSAtom` instances MAY be
|
||||
// garbage-collected.
|
||||
|
||||
struct JSContext;
|
||||
|
||||
|
@ -61,15 +67,8 @@ class ParseContext;
|
|||
struct CompilationInfo;
|
||||
class ParserSharedBase;
|
||||
class FullParseHandler;
|
||||
|
||||
class FunctionBox;
|
||||
|
||||
// This typedef unfortunately needs to be replicated here.
|
||||
using ParserBindingName = AbstractBindingName<const ParserAtom>;
|
||||
|
||||
template <typename Scope>
|
||||
using ParserScopeData = typename Scope::template AbstractData<const ParserAtom>;
|
||||
|
||||
#define FOR_EACH_PARSE_NODE_KIND(F) \
|
||||
F(EmptyStmt, NullaryNode) \
|
||||
F(ExpressionStmt, UnaryNode) \
|
||||
|
@ -748,7 +747,7 @@ class ParseNode {
|
|||
return ParseNodeKind::BinOpFirst <= kind &&
|
||||
kind <= ParseNodeKind::BinOpLast;
|
||||
}
|
||||
inline bool isName(const ParserName* name) const;
|
||||
inline bool isName(PropertyName* name) const;
|
||||
|
||||
/* Boolean attributes. */
|
||||
bool isInParens() const { return pn_parens; }
|
||||
|
@ -851,11 +850,11 @@ class NullaryNode : public ParseNode {
|
|||
};
|
||||
|
||||
class NameNode : public ParseNode {
|
||||
const ParserAtom* atom_; /* lexical name or label atom */
|
||||
JSAtom* atom_; /* lexical name or label atom */
|
||||
PrivateNameKind privateNameKind_ = PrivateNameKind::None;
|
||||
|
||||
public:
|
||||
NameNode(ParseNodeKind kind, const ParserAtom* atom, const TokenPos& pos)
|
||||
NameNode(ParseNodeKind kind, JSAtom* atom, const TokenPos& pos)
|
||||
: ParseNode(kind, pos), atom_(atom) {
|
||||
MOZ_ASSERT(is<NameNode>());
|
||||
}
|
||||
|
@ -875,15 +874,15 @@ class NameNode : public ParseNode {
|
|||
void dumpImpl(GenericPrinter& out, int indent);
|
||||
#endif
|
||||
|
||||
const ParserAtom* atom() const { return atom_; }
|
||||
JSAtom* atom() const { return atom_; }
|
||||
|
||||
const ParserName* name() const {
|
||||
PropertyName* name() const {
|
||||
MOZ_ASSERT(isKind(ParseNodeKind::Name) ||
|
||||
isKind(ParseNodeKind::PrivateName));
|
||||
return atom()->asName();
|
||||
return atom()->asPropertyName();
|
||||
}
|
||||
|
||||
void setAtom(const ParserAtom* atom) { atom_ = atom; }
|
||||
void setAtom(JSAtom* atom) { atom_ = atom; }
|
||||
|
||||
void setPrivateNameKind(PrivateNameKind privateNameKind) {
|
||||
privateNameKind_ = privateNameKind;
|
||||
|
@ -892,7 +891,7 @@ class NameNode : public ParseNode {
|
|||
PrivateNameKind privateNameKind() { return privateNameKind_; }
|
||||
};
|
||||
|
||||
inline bool ParseNode::isName(const ParserName* name) const {
|
||||
inline bool ParseNode::isName(PropertyName* name) const {
|
||||
return getKind() == ParseNodeKind::Name && as<NameNode>().name() == name;
|
||||
}
|
||||
|
||||
|
@ -941,7 +940,7 @@ class UnaryNode : public ParseNode {
|
|||
* or escaped newlines, say). This member function returns true for such
|
||||
* nodes; we use it to determine the extent of the prologue.
|
||||
*/
|
||||
const ParserAtom* isStringExprStatement() const {
|
||||
JSAtom* isStringExprStatement() const {
|
||||
if (isKind(ParseNodeKind::ExpressionStmt)) {
|
||||
if (kid()->isKind(ParseNodeKind::StringExpr) && !kid()->isInParens()) {
|
||||
return kid()->as<NameNode>().atom();
|
||||
|
@ -1553,7 +1552,7 @@ class NumericLiteral : public ParseNode {
|
|||
void setDecimalPoint(DecimalPoint d) { decimalPoint_ = d; }
|
||||
|
||||
// Return the decimal string representation of this numeric literal.
|
||||
const ParserAtom* toAtom(CompilationInfo& compilationInfo) const;
|
||||
JSAtom* toAtom(JSContext* cx) const;
|
||||
};
|
||||
|
||||
class BigIntLiteral : public ParseNode {
|
||||
|
@ -1591,12 +1590,12 @@ class BigIntLiteral : public ParseNode {
|
|||
};
|
||||
|
||||
class LexicalScopeNode : public ParseNode {
|
||||
ParserScopeData<LexicalScope>* bindings;
|
||||
LexicalScope::Data* bindings;
|
||||
ParseNode* body;
|
||||
ScopeKind kind_;
|
||||
|
||||
public:
|
||||
LexicalScopeNode(ParserScopeData<LexicalScope>* bindings, ParseNode* body,
|
||||
LexicalScopeNode(LexicalScope::Data* bindings, ParseNode* body,
|
||||
ScopeKind kind = ScopeKind::Lexical)
|
||||
: ParseNode(ParseNodeKind::LexicalScope, body->pn_pos),
|
||||
bindings(bindings),
|
||||
|
@ -1618,11 +1617,11 @@ class LexicalScopeNode : public ParseNode {
|
|||
void dumpImpl(GenericPrinter& out, int indent);
|
||||
#endif
|
||||
|
||||
ParserScopeData<LexicalScope>* scopeBindings() const {
|
||||
Handle<LexicalScope::Data*> scopeBindings() const {
|
||||
MOZ_ASSERT(!isEmptyScope());
|
||||
// Bindings' GC safety depend on the presence of an AutoKeepAtoms that
|
||||
// the rest of the frontend also depends on.
|
||||
return bindings;
|
||||
return Handle<LexicalScope::Data*>::fromMarkedLocation(&bindings);
|
||||
}
|
||||
|
||||
ParseNode* scopeBody() const { return body; }
|
||||
|
@ -1638,12 +1637,12 @@ class LabeledStatement : public NameNode {
|
|||
ParseNode* statement_;
|
||||
|
||||
public:
|
||||
LabeledStatement(const ParserName* label, ParseNode* stmt, uint32_t begin)
|
||||
LabeledStatement(PropertyName* label, ParseNode* stmt, uint32_t begin)
|
||||
: NameNode(ParseNodeKind::LabelStmt, label,
|
||||
TokenPos(begin, stmt->pn_pos.end)),
|
||||
statement_(stmt) {}
|
||||
|
||||
const ParserName* label() const { return atom()->asName(); }
|
||||
PropertyName* label() const { return atom()->asPropertyName(); }
|
||||
|
||||
ParseNode* statement() const { return statement_; }
|
||||
|
||||
|
@ -1689,10 +1688,10 @@ class CaseClause : public BinaryNode {
|
|||
};
|
||||
|
||||
class LoopControlStatement : public ParseNode {
|
||||
const ParserName* label_; /* target of break/continue statement */
|
||||
PropertyName* label_; /* target of break/continue statement */
|
||||
|
||||
protected:
|
||||
LoopControlStatement(ParseNodeKind kind, const ParserName* label,
|
||||
LoopControlStatement(ParseNodeKind kind, PropertyName* label,
|
||||
const TokenPos& pos)
|
||||
: ParseNode(kind, pos), label_(label) {
|
||||
MOZ_ASSERT(kind == ParseNodeKind::BreakStmt ||
|
||||
|
@ -1702,7 +1701,7 @@ class LoopControlStatement : public ParseNode {
|
|||
|
||||
public:
|
||||
/* Label associated with this break/continue statement, if any. */
|
||||
const ParserName* label() const { return label_; }
|
||||
PropertyName* label() const { return label_; }
|
||||
|
||||
#ifdef DEBUG
|
||||
void dumpImpl(GenericPrinter& out, int indent);
|
||||
|
@ -1723,7 +1722,7 @@ class LoopControlStatement : public ParseNode {
|
|||
|
||||
class BreakStatement : public LoopControlStatement {
|
||||
public:
|
||||
BreakStatement(const ParserName* label, const TokenPos& pos)
|
||||
BreakStatement(PropertyName* label, const TokenPos& pos)
|
||||
: LoopControlStatement(ParseNodeKind::BreakStmt, label, pos) {}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
|
@ -1735,7 +1734,7 @@ class BreakStatement : public LoopControlStatement {
|
|||
|
||||
class ContinueStatement : public LoopControlStatement {
|
||||
public:
|
||||
ContinueStatement(const ParserName* label, const TokenPos& pos)
|
||||
ContinueStatement(PropertyName* label, const TokenPos& pos)
|
||||
: LoopControlStatement(ParseNodeKind::ContinueStmt, label, pos) {}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
|
@ -1923,8 +1922,8 @@ class PropertyAccessBase : public BinaryNode {
|
|||
|
||||
void setExpression(ParseNode* pn) { *unsafeLeftReference() = pn; }
|
||||
|
||||
const ParserName* name() const {
|
||||
return right()->as<NameNode>().atom()->asName();
|
||||
PropertyName& name() const {
|
||||
return *right()->as<NameNode>().atom()->asPropertyName();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -266,13 +266,6 @@ class MOZ_STACK_CLASS ParserSharedBase : public JS::CustomAutoRooter {
|
|||
|
||||
public:
|
||||
CompilationInfo& getCompilationInfo() { return compilationInfo_; }
|
||||
|
||||
JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
|
||||
return compilationInfo_.liftParserAtomToJSAtom(parserAtom);
|
||||
}
|
||||
const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
|
||||
return compilationInfo_.lowerJSAtomToParserAtom(atom);
|
||||
}
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
|
||||
|
@ -368,7 +361,7 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
|
|||
public:
|
||||
bool isUnexpectedEOF() const { return isUnexpectedEOF_; }
|
||||
|
||||
bool isValidStrictBinding(const ParserName* name);
|
||||
bool isValidStrictBinding(PropertyName* name);
|
||||
|
||||
bool hasValidSimpleStrictParameterNames();
|
||||
|
||||
|
@ -376,7 +369,7 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
|
|||
* Create a new function object given a name (which is optional if this is
|
||||
* a function expression).
|
||||
*/
|
||||
JSFunction* newFunction(const ParserAtom* atom, FunctionSyntaxKind kind,
|
||||
JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind);
|
||||
|
||||
|
@ -400,17 +393,15 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
|
|||
}
|
||||
|
||||
public:
|
||||
mozilla::Maybe<ParserGlobalScopeData*> newGlobalScopeData(
|
||||
mozilla::Maybe<GlobalScope::Data*> newGlobalScopeData(
|
||||
ParseContext::Scope& scope);
|
||||
mozilla::Maybe<ParserModuleScopeData*> newModuleScopeData(
|
||||
mozilla::Maybe<ModuleScope::Data*> newModuleScopeData(
|
||||
ParseContext::Scope& scope);
|
||||
mozilla::Maybe<ParserEvalScopeData*> newEvalScopeData(
|
||||
ParseContext::Scope& scope);
|
||||
mozilla::Maybe<ParserFunctionScopeData*> newFunctionScopeData(
|
||||
mozilla::Maybe<EvalScope::Data*> newEvalScopeData(ParseContext::Scope& scope);
|
||||
mozilla::Maybe<FunctionScope::Data*> newFunctionScopeData(
|
||||
ParseContext::Scope& scope, bool hasParameterExprs);
|
||||
mozilla::Maybe<ParserVarScopeData*> newVarScopeData(
|
||||
ParseContext::Scope& scope);
|
||||
mozilla::Maybe<ParserLexicalScopeData*> newLexicalScopeData(
|
||||
mozilla::Maybe<VarScope::Data*> newVarScopeData(ParseContext::Scope& scope);
|
||||
mozilla::Maybe<LexicalScope::Data*> newLexicalScopeData(
|
||||
ParseContext::Scope& scope);
|
||||
|
||||
protected:
|
||||
|
@ -422,15 +413,14 @@ class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
|
|||
// modifier TokenStream::SlashIsDiv, continues a LexicalDeclaration.
|
||||
bool nextTokenContinuesLetDeclaration(TokenKind next);
|
||||
|
||||
bool noteUsedNameInternal(const ParserName* name, NameVisibility visibility,
|
||||
bool noteUsedNameInternal(HandlePropertyName name, NameVisibility visibility,
|
||||
mozilla::Maybe<TokenPos> tokenPosition);
|
||||
|
||||
bool checkAndMarkSuperScope();
|
||||
|
||||
bool leaveInnerFunction(ParseContext* outerpc);
|
||||
|
||||
const ParserAtom* prefixAccessorName(PropertyType propType,
|
||||
const ParserAtom* propAtom);
|
||||
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
|
||||
|
||||
MOZ_MUST_USE bool setSourceMapInfo();
|
||||
|
||||
|
@ -497,7 +487,7 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
|
|||
Node destruct);
|
||||
|
||||
bool noteUsedName(
|
||||
const ParserName* name,
|
||||
HandlePropertyName name,
|
||||
NameVisibility visibility = NameVisibility::Public,
|
||||
mozilla::Maybe<TokenPos> tokenPosition = mozilla::Nothing()) {
|
||||
// If the we are delazifying, the BaseScript already has all the closed-over
|
||||
|
@ -519,18 +509,18 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
|
|||
ScopeKind kind = ScopeKind::Lexical);
|
||||
bool finishFunction(bool isStandaloneFunction = false);
|
||||
|
||||
inline NameNodeType newName(const ParserName* name);
|
||||
inline NameNodeType newName(const ParserName* name, TokenPos pos);
|
||||
inline NameNodeType newName(PropertyName* name);
|
||||
inline NameNodeType newName(PropertyName* name, TokenPos pos);
|
||||
|
||||
inline NameNodeType newPrivateName(const ParserName* name);
|
||||
inline NameNodeType newPrivateName(const ParserName* name, TokenPos pos);
|
||||
inline NameNodeType newPrivateName(PropertyName* name);
|
||||
inline NameNodeType newPrivateName(PropertyName* name, TokenPos pos);
|
||||
|
||||
NameNodeType newInternalDotName(const ParserName* name);
|
||||
NameNodeType newInternalDotName(HandlePropertyName name);
|
||||
NameNodeType newThisName();
|
||||
NameNodeType newDotGeneratorName();
|
||||
|
||||
NameNodeType identifierReference(const ParserName* name);
|
||||
NameNodeType privateNameReference(const ParserName* name);
|
||||
NameNodeType identifierReference(Handle<PropertyName*> name);
|
||||
NameNodeType privateNameReference(Handle<PropertyName*> name);
|
||||
|
||||
Node noSubstitutionTaggedTemplate();
|
||||
|
||||
|
@ -566,7 +556,7 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
|
|||
inline void clearAbortedSyntaxParse();
|
||||
|
||||
public:
|
||||
NameNodeType newPropertyName(const ParserName* key, const TokenPos& pos) {
|
||||
NameNodeType newPropertyName(PropertyName* key, const TokenPos& pos) {
|
||||
return handler_.newPropertyName(key, pos);
|
||||
}
|
||||
|
||||
|
@ -574,8 +564,7 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
|
|||
return handler_.newPropertyAccess(expr, key);
|
||||
}
|
||||
|
||||
FunctionBox* newFunctionBox(FunctionNodeType funNode,
|
||||
const ParserAtom* explicitName,
|
||||
FunctionBox* newFunctionBox(FunctionNodeType funNode, JSAtom* explicitName,
|
||||
FunctionFlags flags, uint32_t toStringStart,
|
||||
Directives directives,
|
||||
GeneratorKind generatorKind,
|
||||
|
@ -993,8 +982,8 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
ListNodeType nodeList, TokenKind* ttp);
|
||||
|
||||
inline bool trySyntaxParseInnerFunction(
|
||||
FunctionNodeType* funNode, const ParserAtom* explicitName,
|
||||
FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
|
||||
FunctionNodeType* funNode, HandleAtom explicitName, FunctionFlags flags,
|
||||
uint32_t toStringStart, InHandling inHandling,
|
||||
YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
@ -1199,8 +1188,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
BinaryNodeType importExpr(YieldHandling yieldHandling, bool allowCallSyntax);
|
||||
|
||||
FunctionNodeType methodDefinition(uint32_t toStringStart,
|
||||
PropertyType propType,
|
||||
const ParserAtom* funName);
|
||||
PropertyType propType, HandleAtom funName);
|
||||
|
||||
/*
|
||||
* Additional JS parsers.
|
||||
|
@ -1210,9 +1198,9 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
|
||||
FunctionNodeType functionDefinition(
|
||||
FunctionNodeType funNode, uint32_t toStringStart, InHandling inHandling,
|
||||
YieldHandling yieldHandling, const ParserAtom* name,
|
||||
FunctionSyntaxKind kind, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind, bool tryAnnexB = false);
|
||||
YieldHandling yieldHandling, HandleAtom name, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB = false);
|
||||
|
||||
// Parse a function body. Pass StatementListBody if the body is a list of
|
||||
// statements; pass ExpressionBody if the body is a single expression.
|
||||
|
@ -1235,7 +1223,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
YieldHandling yieldHandling,
|
||||
TokenKind tt);
|
||||
|
||||
inline bool checkExportedName(const ParserAtom* exportName);
|
||||
inline bool checkExportedName(JSAtom* exportName);
|
||||
inline bool checkExportedNamesForArrayBinding(ListNodeType array);
|
||||
inline bool checkExportedNamesForObjectBinding(ListNodeType obj);
|
||||
inline bool checkExportedNamesForDeclaration(Node node);
|
||||
|
@ -1267,41 +1255,42 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
MOZ_MUST_USE bool classMember(
|
||||
YieldHandling yieldHandling,
|
||||
const ParseContext::ClassStatement& classStmt,
|
||||
const ParserName* className, uint32_t classStartOffset,
|
||||
HandlePropertyName className, uint32_t classStartOffset,
|
||||
HasHeritage hasHeritage, ClassInitializedMembers& classInitializedMembers,
|
||||
ListNodeType& classMembers, bool* done);
|
||||
MOZ_MUST_USE bool finishClassConstructor(
|
||||
const ParseContext::ClassStatement& classStmt,
|
||||
const ParserName* className, HasHeritage hasHeritage,
|
||||
HandlePropertyName className, HasHeritage hasHeritage,
|
||||
uint32_t classStartOffset, uint32_t classEndOffset,
|
||||
const ClassInitializedMembers& classInitializedMembers,
|
||||
ListNodeType& classMembers);
|
||||
|
||||
FunctionNodeType privateMethodInitializer(const ParserAtom* propAtom,
|
||||
const ParserAtom* storedMethodAtom);
|
||||
FunctionNodeType privateMethodInitializer(HandleAtom propAtom,
|
||||
HandleAtom storedMethodAtom);
|
||||
FunctionNodeType fieldInitializerOpt(
|
||||
Node name, const ParserAtom* atom,
|
||||
Node name, HandleAtom atom,
|
||||
ClassInitializedMembers& classInitializedMembers, bool isStatic,
|
||||
HasHeritage hasHeritage);
|
||||
FunctionNodeType synthesizeConstructor(const ParserAtom* className,
|
||||
FunctionNodeType synthesizeConstructor(HandleAtom className,
|
||||
uint32_t classNameOffset,
|
||||
HasHeritage hasHeritage);
|
||||
|
||||
bool checkBindingIdentifier(const ParserName* ident, uint32_t offset,
|
||||
bool checkBindingIdentifier(PropertyName* ident, uint32_t offset,
|
||||
YieldHandling yieldHandling,
|
||||
TokenKind hint = TokenKind::Limit);
|
||||
|
||||
const ParserName* labelOrIdentifierReference(YieldHandling yieldHandling);
|
||||
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling);
|
||||
|
||||
const ParserName* labelIdentifier(YieldHandling yieldHandling) {
|
||||
PropertyName* labelIdentifier(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling);
|
||||
}
|
||||
|
||||
const ParserName* identifierReference(YieldHandling yieldHandling) {
|
||||
PropertyName* identifierReference(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling);
|
||||
}
|
||||
|
||||
bool matchLabel(YieldHandling yieldHandling, const ParserName** labelOut);
|
||||
bool matchLabel(YieldHandling yieldHandling,
|
||||
MutableHandle<PropertyName*> label);
|
||||
|
||||
// Indicate if the next token (tokenized with SlashIsRegExp) is |in| or |of|.
|
||||
// If so, consume it.
|
||||
|
@ -1314,10 +1303,10 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
void reportMissingClosing(unsigned errorNumber, unsigned noteNumber,
|
||||
uint32_t openedPos);
|
||||
|
||||
void reportRedeclaration(const ParserName* name, DeclarationKind prevKind,
|
||||
void reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind,
|
||||
TokenPos pos, uint32_t prevPos);
|
||||
bool notePositionalFormalParameter(FunctionNodeType funNode,
|
||||
const ParserName* name, uint32_t beginPos,
|
||||
HandlePropertyName name, uint32_t beginPos,
|
||||
bool disallowDuplicateParams,
|
||||
bool* duplicatedParam);
|
||||
|
||||
|
@ -1329,12 +1318,12 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
Node propertyName(YieldHandling yieldHandling,
|
||||
PropertyNameContext propertyNameContext,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl,
|
||||
ListNodeType propList, const ParserAtom** propAtomOut);
|
||||
ListNodeType propList, MutableHandleAtom propAtom);
|
||||
Node propertyOrMethodName(YieldHandling yieldHandling,
|
||||
PropertyNameContext propertyNameContext,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl,
|
||||
ListNodeType propList, PropertyType* propType,
|
||||
const ParserAtom** propAtomOut);
|
||||
MutableHandleAtom propAtom);
|
||||
UnaryNodeType computedPropertyName(
|
||||
YieldHandling yieldHandling,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl,
|
||||
|
@ -1377,7 +1366,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
|
||||
inline BigIntLiteralType newBigInt();
|
||||
|
||||
const ParserAtom* bigIntAtom();
|
||||
JSAtom* bigIntAtom();
|
||||
|
||||
enum class OptionalKind {
|
||||
NonOptional = 0,
|
||||
|
@ -1398,18 +1387,17 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
// Match the current token against the BindingIdentifier production with
|
||||
// the given Yield parameter. If there is no match, report a syntax
|
||||
// error.
|
||||
const ParserName* bindingIdentifier(YieldHandling yieldHandling);
|
||||
PropertyName* bindingIdentifier(YieldHandling yieldHandling);
|
||||
|
||||
bool checkLabelOrIdentifierReference(const ParserName* ident, uint32_t offset,
|
||||
bool checkLabelOrIdentifierReference(PropertyName* ident, uint32_t offset,
|
||||
YieldHandling yieldHandling,
|
||||
TokenKind hint = TokenKind::Limit);
|
||||
|
||||
ListNodeType statementList(YieldHandling yieldHandling);
|
||||
|
||||
MOZ_MUST_USE FunctionNodeType innerFunction(
|
||||
FunctionNodeType funNode, ParseContext* outerpc,
|
||||
const ParserAtom* explicitName, FunctionFlags flags,
|
||||
uint32_t toStringStart, InHandling inHandling,
|
||||
FunctionNodeType funNode, ParseContext* outerpc, HandleAtom explicitName,
|
||||
FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
|
||||
YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
@ -1426,10 +1414,10 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
|
|||
// next token could be a RegExp literal beginning a new ExpressionStatement.
|
||||
bool matchOrInsertSemicolon(Modifier modifier = TokenStream::SlashIsRegExp);
|
||||
|
||||
bool noteDeclaredName(const ParserName* name, DeclarationKind kind,
|
||||
bool noteDeclaredName(HandlePropertyName name, DeclarationKind kind,
|
||||
TokenPos pos);
|
||||
|
||||
bool noteDeclaredPrivateName(Node nameNode, const ParserName* name,
|
||||
bool noteDeclaredPrivateName(Node nameNode, HandlePropertyName name,
|
||||
PropertyType propType, TokenPos pos);
|
||||
|
||||
private:
|
||||
|
@ -1533,7 +1521,7 @@ class MOZ_STACK_CLASS Parser<SyntaxParseHandler, Unit> final
|
|||
// |using| the whole thing into existence because of the visibility
|
||||
// distinction, so we instead must manually delegate the required overload.
|
||||
|
||||
const ParserName* bindingIdentifier(YieldHandling yieldHandling) {
|
||||
PropertyName* bindingIdentifier(YieldHandling yieldHandling) {
|
||||
return Base::bindingIdentifier(yieldHandling);
|
||||
}
|
||||
|
||||
|
@ -1550,7 +1538,7 @@ class MOZ_STACK_CLASS Parser<SyntaxParseHandler, Unit> final
|
|||
|
||||
inline BinaryNodeType importDeclaration();
|
||||
inline bool checkLocalExportNames(ListNodeType node);
|
||||
inline bool checkExportedName(const ParserAtom* exportName);
|
||||
inline bool checkExportedName(JSAtom* exportName);
|
||||
inline bool checkExportedNamesForArrayBinding(ListNodeType array);
|
||||
inline bool checkExportedNamesForObjectBinding(ListNodeType obj);
|
||||
inline bool checkExportedNamesForDeclaration(Node node);
|
||||
|
@ -1560,8 +1548,8 @@ class MOZ_STACK_CLASS Parser<SyntaxParseHandler, Unit> final
|
|||
inline bool checkExportedNameForClause(NameNodeType nameNode);
|
||||
|
||||
bool trySyntaxParseInnerFunction(
|
||||
FunctionNodeType* funNode, const ParserAtom* explicitName,
|
||||
FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
|
||||
FunctionNodeType* funNode, HandleAtom explicitName, FunctionFlags flags,
|
||||
uint32_t toStringStart, InHandling inHandling,
|
||||
YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
@ -1677,7 +1665,7 @@ class MOZ_STACK_CLASS Parser<FullParseHandler, Unit> final
|
|||
// |using| the whole thing into existence because of the visibility
|
||||
// distinction, so we instead must manually delegate the required overload.
|
||||
|
||||
const ParserName* bindingIdentifier(YieldHandling yieldHandling) {
|
||||
PropertyName* bindingIdentifier(YieldHandling yieldHandling) {
|
||||
return Base::bindingIdentifier(yieldHandling);
|
||||
}
|
||||
|
||||
|
@ -1697,7 +1685,7 @@ class MOZ_STACK_CLASS Parser<FullParseHandler, Unit> final
|
|||
|
||||
BinaryNodeType importDeclaration();
|
||||
bool checkLocalExportNames(ListNodeType node);
|
||||
bool checkExportedName(const ParserAtom* exportName);
|
||||
bool checkExportedName(JSAtom* exportName);
|
||||
bool checkExportedNamesForArrayBinding(ListNodeType array);
|
||||
bool checkExportedNamesForObjectBinding(ListNodeType obj);
|
||||
bool checkExportedNamesForDeclaration(Node node);
|
||||
|
@ -1707,8 +1695,8 @@ class MOZ_STACK_CLASS Parser<FullParseHandler, Unit> final
|
|||
inline bool checkExportedNameForClause(NameNodeType nameNode);
|
||||
|
||||
bool trySyntaxParseInnerFunction(
|
||||
FunctionNodeType* funNode, const ParserAtom* explicitName,
|
||||
FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
|
||||
FunctionNodeType* funNode, HandleAtom explicitName, FunctionFlags flags,
|
||||
uint32_t toStringStart, InHandling inHandling,
|
||||
YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
@ -1750,9 +1738,9 @@ class MOZ_STACK_CLASS Parser<FullParseHandler, Unit> final
|
|||
|
||||
bool namedImportsOrNamespaceImport(TokenKind tt, ListNodeType importSpecSet);
|
||||
|
||||
const ParserName* importedBinding() { return bindingIdentifier(YieldIsName); }
|
||||
PropertyName* importedBinding() { return bindingIdentifier(YieldIsName); }
|
||||
|
||||
bool checkLocalExportName(const ParserName* ident, uint32_t offset) {
|
||||
bool checkLocalExportName(PropertyName* ident, uint32_t offset) {
|
||||
return checkLabelOrIdentifierReference(ident, offset, YieldIsName);
|
||||
}
|
||||
|
||||
|
@ -1849,38 +1837,33 @@ class MOZ_STACK_CLASS AutoInParametersOfAsyncFunction {
|
|||
}
|
||||
};
|
||||
|
||||
ParserGlobalScopeData* NewEmptyGlobalScopeData(JSContext* cx, LifoAlloc& alloc,
|
||||
GlobalScope::Data* NewEmptyGlobalScopeData(JSContext* cx, LifoAlloc& alloc,
|
||||
uint32_t numBindings);
|
||||
|
||||
ParserVarScopeData* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc,
|
||||
VarScope::Data* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc,
|
||||
uint32_t numBindings);
|
||||
|
||||
ParserLexicalScopeData* NewEmptyLexicalScopeData(JSContext* cx,
|
||||
LifoAlloc& alloc,
|
||||
LexicalScope::Data* NewEmptyLexicalScopeData(JSContext* cx, LifoAlloc& alloc,
|
||||
uint32_t numBindings);
|
||||
|
||||
ParserFunctionScopeData* NewEmptyFunctionScopeData(JSContext* cx,
|
||||
LifoAlloc& alloc,
|
||||
FunctionScope::Data* NewEmptyFunctionScopeData(JSContext* cx, LifoAlloc& alloc,
|
||||
uint32_t numBindings);
|
||||
|
||||
mozilla::Maybe<ParserGlobalScopeData*> NewGlobalScopeData(
|
||||
mozilla::Maybe<GlobalScope::Data*> NewGlobalScopeData(
|
||||
JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
|
||||
ParseContext* pc);
|
||||
|
||||
mozilla::Maybe<ParserEvalScopeData*> NewEvalScopeData(
|
||||
JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
|
||||
ParseContext* pc);
|
||||
|
||||
mozilla::Maybe<ParserFunctionScopeData*> NewFunctionScopeData(
|
||||
JSContext* context, ParseContext::Scope& scope, bool hasParameterExprs,
|
||||
LifoAlloc& alloc, ParseContext* pc);
|
||||
|
||||
mozilla::Maybe<ParserVarScopeData*> NewVarScopeData(JSContext* context,
|
||||
mozilla::Maybe<EvalScope::Data*> NewEvalScopeData(JSContext* context,
|
||||
ParseContext::Scope& scope,
|
||||
LifoAlloc& alloc,
|
||||
ParseContext* pc);
|
||||
|
||||
mozilla::Maybe<ParserLexicalScopeData*> NewLexicalScopeData(
|
||||
mozilla::Maybe<FunctionScope::Data*> NewFunctionScopeData(
|
||||
JSContext* context, ParseContext::Scope& scope, bool hasParameterExprs,
|
||||
LifoAlloc& alloc, ParseContext* pc);
|
||||
mozilla::Maybe<VarScope::Data*> NewVarScopeData(JSContext* context,
|
||||
ParseContext::Scope& scope,
|
||||
LifoAlloc& alloc,
|
||||
ParseContext* pc);
|
||||
mozilla::Maybe<LexicalScope::Data*> NewLexicalScopeData(
|
||||
JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
|
||||
ParseContext* pc);
|
||||
|
||||
|
|
|
@ -16,6 +16,15 @@
|
|||
#include "vm/Runtime.h"
|
||||
#include "vm/StringType.h"
|
||||
|
||||
//
|
||||
// Parser-Atoms should be disabled for now. This check ensures that.
|
||||
// NOTE: This will be removed when the final transition patches from
|
||||
// JS-atoms to parser-atoms lands.
|
||||
//
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
# error "Parser atoms define should remain disabled until this is removed."
|
||||
#endif
|
||||
|
||||
using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
|
@ -326,28 +335,18 @@ static void FillChar16Buffer(char16_t* buf, const ParserAtomEntry* ent) {
|
|||
}
|
||||
|
||||
JS::Result<const ParserAtom*, OOM&> ParserAtomsTable::concatAtoms(
|
||||
JSContext* cx, mozilla::Range<const ParserAtom*> atoms) {
|
||||
bool latin1 = true;
|
||||
uint32_t catLen = 0;
|
||||
for (const ParserAtom* atom : atoms) {
|
||||
if (!atom->hasLatin1Chars()) {
|
||||
latin1 = false;
|
||||
}
|
||||
// Overflow check here, length
|
||||
if (atom->length() >= (ParserAtomEntry::MAX_LENGTH - catLen)) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
catLen += atom->length();
|
||||
}
|
||||
JSContext* cx, const ParserAtom* prefix, const ParserAtom* suffix) {
|
||||
bool latin1 = prefix->hasLatin1Chars() && suffix->hasLatin1Chars();
|
||||
size_t prefixLength = prefix->length();
|
||||
size_t suffixLength = suffix->length();
|
||||
size_t catLen = prefixLength + suffixLength;
|
||||
|
||||
if (latin1) {
|
||||
if (catLen <= ParserAtomEntry::MaxInline<Latin1Char>()) {
|
||||
Latin1Char buf[ParserAtomEntry::MaxInline<Latin1Char>()];
|
||||
size_t offset = 0;
|
||||
for (const ParserAtom* atom : atoms) {
|
||||
mozilla::PodCopy(buf + offset, atom->latin1Chars(), atom->length());
|
||||
offset += atom->length();
|
||||
}
|
||||
mozilla::PodCopy(buf, prefix->latin1Chars(), prefixLength);
|
||||
mozilla::PodCopy(buf + prefixLength, suffix->latin1Chars(), suffixLength);
|
||||
|
||||
return internLatin1(cx, buf, catLen);
|
||||
}
|
||||
|
||||
|
@ -356,12 +355,9 @@ JS::Result<const ParserAtom*, OOM&> ParserAtomsTable::concatAtoms(
|
|||
if (!copy) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
size_t offset = 0;
|
||||
for (const ParserAtom* atom : atoms) {
|
||||
mozilla::PodCopy(copy.get() + offset, atom->latin1Chars(),
|
||||
atom->length());
|
||||
offset += atom->length();
|
||||
}
|
||||
mozilla::PodCopy(copy.get(), prefix->latin1Chars(), prefixLength);
|
||||
mozilla::PodCopy(copy.get() + prefixLength, suffix->latin1Chars(),
|
||||
suffixLength);
|
||||
|
||||
InflatedChar16Sequence<Latin1Char> seq(copy.get(), catLen);
|
||||
|
||||
|
@ -380,11 +376,8 @@ JS::Result<const ParserAtom*, OOM&> ParserAtomsTable::concatAtoms(
|
|||
|
||||
if (catLen <= ParserAtomEntry::MaxInline<char16_t>()) {
|
||||
char16_t buf[ParserAtomEntry::MaxInline<char16_t>()];
|
||||
size_t offset = 0;
|
||||
for (const ParserAtom* atom : atoms) {
|
||||
FillChar16Buffer(buf + offset, atom);
|
||||
offset += atom->length();
|
||||
}
|
||||
FillChar16Buffer(buf, prefix);
|
||||
FillChar16Buffer(buf + prefixLength, suffix);
|
||||
|
||||
InflatedChar16Sequence<char16_t> seq(buf, catLen);
|
||||
|
||||
|
@ -406,11 +399,8 @@ JS::Result<const ParserAtom*, OOM&> ParserAtomsTable::concatAtoms(
|
|||
if (!copy) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
size_t offset = 0;
|
||||
for (const ParserAtom* atom : atoms) {
|
||||
FillChar16Buffer(copy.get() + offset, atom);
|
||||
offset += atom->length();
|
||||
}
|
||||
FillChar16Buffer(copy.get(), prefix);
|
||||
FillChar16Buffer(copy.get() + prefixLength, suffix);
|
||||
|
||||
InflatedChar16Sequence<char16_t> seq(copy.get(), catLen);
|
||||
|
||||
|
@ -439,7 +429,7 @@ const ParserAtom* WellKnownParserAtoms::lookupChar16Seq(
|
|||
}
|
||||
|
||||
bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
||||
const char* str, JSAtom* jsatom) {
|
||||
const char* str) {
|
||||
MOZ_ASSERT(name != nullptr);
|
||||
|
||||
unsigned int len = strlen(str);
|
||||
|
@ -476,7 +466,6 @@ bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
|||
}
|
||||
entry = maybeEntry.unwrap();
|
||||
}
|
||||
entry->jsatom_ = jsatom;
|
||||
|
||||
// Save name for returning after moving entry into set.
|
||||
const ParserName* nm = entry.get()->asName();
|
||||
|
@ -490,14 +479,14 @@ 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)) { \
|
||||
if (!initSingle(cx, &(id), text)) { \
|
||||
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)) { \
|
||||
if (!initSingle(cx, &(name), #name)) { \
|
||||
return false; \
|
||||
}
|
||||
JS_FOR_EACH_PROTOTYPE(COMMON_NAME_INIT_)
|
||||
|
@ -510,6 +499,7 @@ bool WellKnownParserAtoms::init(JSContext* cx) {
|
|||
} /* namespace js */
|
||||
|
||||
bool JSRuntime::initializeParserAtoms(JSContext* cx) {
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
MOZ_ASSERT(!commonParserNames);
|
||||
|
||||
if (parentRuntime) {
|
||||
|
@ -524,11 +514,18 @@ bool JSRuntime::initializeParserAtoms(JSContext* cx) {
|
|||
}
|
||||
|
||||
commonParserNames = names.release();
|
||||
#else
|
||||
commonParserNames = nullptr;
|
||||
#endif // JS_PARSER_ATOMS
|
||||
return true;
|
||||
}
|
||||
|
||||
void JSRuntime::finishParserAtoms() {
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
if (!parentRuntime) {
|
||||
js_delete(commonParserNames.ref());
|
||||
}
|
||||
#else
|
||||
MOZ_ASSERT(!commonParserNames);
|
||||
#endif // JS_PARSER_ATOMS
|
||||
}
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
|
||||
#include "mozilla/DebugOnly.h" // mozilla::DebugOnly
|
||||
#include "mozilla/HashFunctions.h" // HashString
|
||||
#include "mozilla/Range.h" // mozilla::Range
|
||||
#include "mozilla/Variant.h" // mozilla::Variant
|
||||
|
||||
#include "ds/LifoAlloc.h" // LifoAlloc
|
||||
#include "js/GCPolicyAPI.h" // JS::GCPolicy, JS::IgnoreGCPolicy
|
||||
#include "js/HashTable.h" // HashSet
|
||||
#include "js/UniquePtr.h" // js::UniquePtr
|
||||
#include "js/Vector.h" // Vector
|
||||
|
@ -180,6 +178,7 @@ class alignas(alignof(void*)) ParserAtomEntry {
|
|||
}
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
// Owned characters, either 8-bit Latin1Char, or 16-bit char16_t
|
||||
ContentPtrVariant variant_;
|
||||
|
@ -193,15 +192,9 @@ class alignas(alignof(void*)) ParserAtomEntry {
|
|||
// 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;
|
||||
|
||||
public:
|
||||
static const uint32_t MAX_LENGTH = JSString::MAX_LENGTH;
|
||||
|
||||
template <typename CharT>
|
||||
ParserAtomEntry(mozilla::UniquePtr<CharT[], JS::FreePolicy> chars,
|
||||
uint32_t length, HashNumber hash)
|
||||
|
@ -256,12 +249,6 @@ class alignas(alignof(void*)) ParserAtomEntry {
|
|||
MOZ_ASSERT(hasTwoByteChars());
|
||||
return variant_.getUnchecked<char16_t>();
|
||||
}
|
||||
mozilla::Range<const Latin1Char> latin1Range() const {
|
||||
return mozilla::Range(latin1Chars(), length_);
|
||||
}
|
||||
mozilla::Range<const char16_t> twoByteRange() const {
|
||||
return mozilla::Range(twoByteChars(), length_);
|
||||
}
|
||||
|
||||
bool isIndex(uint32_t* indexp) const;
|
||||
bool isIndex() const {
|
||||
|
@ -368,8 +355,7 @@ class WellKnownParserAtoms {
|
|||
TempAllocPolicy>;
|
||||
EntrySet entrySet_;
|
||||
|
||||
bool initSingle(JSContext* cx, const ParserName** name, const char* str,
|
||||
JSAtom* jsatom);
|
||||
bool initSingle(JSContext* cx, const ParserName** name, const char* str);
|
||||
|
||||
public:
|
||||
explicit WellKnownParserAtoms(JSContext* cx) : entrySet_(cx) {}
|
||||
|
@ -462,8 +448,9 @@ class ParserAtomsTable {
|
|||
|
||||
JS::Result<const ParserAtom*, OOM&> internJSAtom(JSContext* cx, JSAtom* atom);
|
||||
|
||||
JS::Result<const ParserAtom*, OOM&> concatAtoms(
|
||||
JSContext* cx, mozilla::Range<const ParserAtom*> atoms);
|
||||
JS::Result<const ParserAtom*, OOM&> concatAtoms(JSContext* cx,
|
||||
const ParserAtom* prefix,
|
||||
const ParserAtom* suffix);
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
|
@ -515,11 +502,4 @@ inline bool ParserAtomEntry::equalsSeq(
|
|||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
||||
namespace JS {
|
||||
// Dummy trace policy until tracing is removed.
|
||||
template <>
|
||||
struct GCPolicy<const js::frontend::ParserAtom*>
|
||||
: IgnoreGCPolicy<const js::frontend::ParserAtom*> {};
|
||||
} // namespace JS
|
||||
|
||||
#endif // frontend_ParserAtom_h
|
||||
|
|
|
@ -18,7 +18,7 @@ using namespace js::frontend;
|
|||
PropOpEmitter::PropOpEmitter(BytecodeEmitter* bce, Kind kind, ObjKind objKind)
|
||||
: bce_(bce), kind_(kind), objKind_(objKind) {}
|
||||
|
||||
bool PropOpEmitter::prepareAtomIndex(const ParserAtom* prop) {
|
||||
bool PropOpEmitter::prepareAtomIndex(JSAtom* prop) {
|
||||
if (!bce_->makeAtomIndex(prop, &propAtomIndex_)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ bool PropOpEmitter::prepareForObj() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PropOpEmitter::emitGet(const ParserAtom* prop) {
|
||||
bool PropOpEmitter::emitGet(JSAtom* prop) {
|
||||
MOZ_ASSERT(state_ == State::Obj);
|
||||
|
||||
if (!prepareAtomIndex(prop)) {
|
||||
|
@ -134,7 +134,7 @@ bool PropOpEmitter::skipObjAndRhs() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PropOpEmitter::emitDelete(const ParserAtom* prop) {
|
||||
bool PropOpEmitter::emitDelete(JSAtom* prop) {
|
||||
MOZ_ASSERT_IF(!isSuper(), state_ == State::Obj);
|
||||
MOZ_ASSERT_IF(isSuper(), state_ == State::Start);
|
||||
MOZ_ASSERT(isDelete());
|
||||
|
@ -174,7 +174,7 @@ bool PropOpEmitter::emitDelete(const ParserAtom* prop) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PropOpEmitter::emitAssignment(const ParserAtom* prop) {
|
||||
bool PropOpEmitter::emitAssignment(JSAtom* prop) {
|
||||
MOZ_ASSERT(isSimpleAssignment() || isPropInit() || isCompoundAssignment());
|
||||
MOZ_ASSERT(state_ == State::Rhs);
|
||||
|
||||
|
@ -202,7 +202,7 @@ bool PropOpEmitter::emitAssignment(const ParserAtom* prop) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PropOpEmitter::emitIncDec(const ParserAtom* prop) {
|
||||
bool PropOpEmitter::emitIncDec(JSAtom* prop) {
|
||||
MOZ_ASSERT(state_ == State::Obj);
|
||||
MOZ_ASSERT(isIncDec());
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace js {
|
|||
namespace frontend {
|
||||
|
||||
struct BytecodeEmitter;
|
||||
class ParserAtom;
|
||||
|
||||
// Class for emitting bytecode for property operation.
|
||||
//
|
||||
|
@ -233,22 +232,22 @@ class MOZ_STACK_CLASS PropOpEmitter {
|
|||
return kind_ == Kind::PostIncrement || kind_ == Kind::PreIncrement;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool prepareAtomIndex(const ParserAtom* prop);
|
||||
MOZ_MUST_USE bool prepareAtomIndex(JSAtom* prop);
|
||||
|
||||
public:
|
||||
MOZ_MUST_USE bool prepareForObj();
|
||||
|
||||
MOZ_MUST_USE bool emitGet(const ParserAtom* prop);
|
||||
MOZ_MUST_USE bool emitGet(JSAtom* prop);
|
||||
|
||||
MOZ_MUST_USE bool prepareForRhs();
|
||||
MOZ_MUST_USE bool skipObjAndRhs();
|
||||
|
||||
MOZ_MUST_USE bool emitDelete(const ParserAtom* prop);
|
||||
MOZ_MUST_USE bool emitDelete(JSAtom* prop);
|
||||
|
||||
// `prop` can be nullptr for CompoundAssignment.
|
||||
MOZ_MUST_USE bool emitAssignment(const ParserAtom* prop);
|
||||
MOZ_MUST_USE bool emitAssignment(JSAtom* prop);
|
||||
|
||||
MOZ_MUST_USE bool emitIncDec(const ParserAtom* prop);
|
||||
MOZ_MUST_USE bool emitIncDec(JSAtom* prop);
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
|
|
|
@ -16,13 +16,6 @@ namespace frontend {
|
|||
inline Directives::Directives(ParseContext* parent)
|
||||
: strict_(parent->sc()->strict()), asmJS_(parent->useAsmOrInsideUseAsm()) {}
|
||||
|
||||
inline JSAtom* SharedContext::liftParserAtomToJSAtom(const ParserAtom* atomId) {
|
||||
return compilationInfo_.liftParserAtomToJSAtom(atomId);
|
||||
}
|
||||
inline const ParserAtom* SharedContext::lowerJSAtomToParserAtom(JSAtom* atom) {
|
||||
return compilationInfo_.lowerJSAtomToParserAtom(atom);
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
} // namespace js
|
||||
|
|
|
@ -205,7 +205,7 @@ EvalSharedContext::EvalSharedContext(JSContext* cx,
|
|||
CompilationInfo& compilationInfo,
|
||||
Directives directives, SourceExtent extent)
|
||||
: SharedContext(cx, Kind::Eval, compilationInfo, directives, extent),
|
||||
bindings(nullptr) {
|
||||
bindings(cx) {
|
||||
// Eval inherits syntax and binding rules from enclosing environment.
|
||||
allowNewTarget_ = compilationInfo.scopeContext.allowNewTarget;
|
||||
allowSuperProperty_ = compilationInfo.scopeContext.allowSuperProperty;
|
||||
|
@ -222,7 +222,7 @@ bool FunctionBox::atomsAreKept() { return cx_->zone()->hasKeptAtoms(); }
|
|||
FunctionBox::FunctionBox(JSContext* cx, FunctionBox* traceListHead,
|
||||
SourceExtent extent, CompilationInfo& compilationInfo,
|
||||
Directives directives, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind, const ParserAtom* atom,
|
||||
FunctionAsyncKind asyncKind, JSAtom* atom,
|
||||
FunctionFlags flags, FunctionIndex index,
|
||||
TopLevelFunction isTopLevel)
|
||||
: SharedContext(cx, Kind::FunctionBox, compilationInfo, directives, extent),
|
||||
|
@ -381,7 +381,11 @@ void FunctionBox::TraceList(JSTracer* trc, FunctionBox* listHead) {
|
|||
}
|
||||
}
|
||||
|
||||
void FunctionBox::trace(JSTracer* trc) {}
|
||||
void FunctionBox::trace(JSTracer* trc) {
|
||||
if (atom_) {
|
||||
TraceRoot(trc, &atom_, "funbox-atom");
|
||||
}
|
||||
}
|
||||
|
||||
ModuleSharedContext::ModuleSharedContext(JSContext* cx,
|
||||
CompilationInfo& compilationInfo,
|
||||
|
@ -389,7 +393,7 @@ ModuleSharedContext::ModuleSharedContext(JSContext* cx,
|
|||
SourceExtent extent)
|
||||
: SharedContext(cx, Kind::Module, compilationInfo, Directives(true),
|
||||
extent),
|
||||
bindings(nullptr),
|
||||
bindings(cx),
|
||||
builder(builder) {
|
||||
thisBinding_ = ThisBinding::Module;
|
||||
setFlag(ImmutableFlags::HasModuleGoal);
|
||||
|
|
|
@ -107,21 +107,6 @@ class GlobalSharedContext;
|
|||
class EvalSharedContext;
|
||||
class ModuleSharedContext;
|
||||
|
||||
using ParserBindingName = AbstractBindingName<const ParserAtom>;
|
||||
using ParserBindingIter = AbstractBindingIter<const ParserAtom>;
|
||||
|
||||
using BaseParserScopeData = AbstractBaseScopeData<const ParserAtom>;
|
||||
|
||||
template <typename Scope>
|
||||
using ParserScopeData = typename Scope::template AbstractData<const ParserAtom>;
|
||||
|
||||
using ParserGlobalScopeData = ParserScopeData<GlobalScope>;
|
||||
using ParserEvalScopeData = ParserScopeData<EvalScope>;
|
||||
using ParserLexicalScopeData = ParserScopeData<LexicalScope>;
|
||||
using ParserFunctionScopeData = ParserScopeData<FunctionScope>;
|
||||
using ParserModuleScopeData = ParserScopeData<ModuleScope>;
|
||||
using ParserVarScopeData = ParserScopeData<VarScope>;
|
||||
|
||||
#define FLAG_GETTER(enumName, enumEntry, lowerName, name) \
|
||||
public: \
|
||||
bool lowerName() const { return hasFlag(enumName::enumEntry); }
|
||||
|
@ -275,9 +260,6 @@ class SharedContext {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
inline JSAtom* liftParserAtomToJSAtom(const ParserAtom* atomId);
|
||||
inline const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom);
|
||||
|
||||
void copyScriptFields(ScriptStencil& stencil);
|
||||
};
|
||||
|
||||
|
@ -285,14 +267,14 @@ class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext {
|
|||
ScopeKind scopeKind_;
|
||||
|
||||
public:
|
||||
ParserGlobalScopeData* bindings;
|
||||
Rooted<GlobalScope::Data*> bindings;
|
||||
|
||||
GlobalSharedContext(JSContext* cx, ScopeKind scopeKind,
|
||||
CompilationInfo& compilationInfo, Directives directives,
|
||||
SourceExtent extent)
|
||||
: SharedContext(cx, Kind::Global, compilationInfo, directives, extent),
|
||||
scopeKind_(scopeKind),
|
||||
bindings(nullptr) {
|
||||
bindings(cx) {
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global ||
|
||||
scopeKind == ScopeKind::NonSyntactic);
|
||||
MOZ_ASSERT(thisBinding_ == ThisBinding::Global);
|
||||
|
@ -308,7 +290,7 @@ inline GlobalSharedContext* SharedContext::asGlobalContext() {
|
|||
|
||||
class MOZ_STACK_CLASS EvalSharedContext : public SharedContext {
|
||||
public:
|
||||
ParserEvalScopeData* bindings;
|
||||
Rooted<EvalScope::Data*> bindings;
|
||||
|
||||
EvalSharedContext(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
Directives directives, SourceExtent extent);
|
||||
|
@ -341,20 +323,20 @@ class FunctionBox : public SharedContext {
|
|||
mozilla::Maybe<ScopeIndex> enclosingScopeIndex_;
|
||||
|
||||
// Names from the named lambda scope, if a named lambda.
|
||||
ParserLexicalScopeData* namedLambdaBindings_ = nullptr;
|
||||
LexicalScope::Data* namedLambdaBindings_ = nullptr;
|
||||
|
||||
// Names from the function scope.
|
||||
ParserFunctionScopeData* functionScopeBindings_ = nullptr;
|
||||
FunctionScope::Data* functionScopeBindings_ = nullptr;
|
||||
|
||||
// Names from the extra 'var' scope of the function, if the parameter list
|
||||
// has expressions.
|
||||
ParserVarScopeData* extraVarScopeBindings_ = nullptr;
|
||||
VarScope::Data* extraVarScopeBindings_ = nullptr;
|
||||
|
||||
// The explicit or implicit name of the function. The FunctionFlags indicate
|
||||
// the kind of name.
|
||||
// This is copied to ScriptStencil.
|
||||
// Any update after the copy should be synced to the ScriptStencil.
|
||||
const ParserAtom* atom_ = nullptr;
|
||||
JSAtom* atom_ = nullptr;
|
||||
|
||||
// Index into CompilationInfo::{funcData, functions}.
|
||||
FunctionIndex funcDataIndex_ = FunctionIndex(-1);
|
||||
|
@ -430,8 +412,8 @@ class FunctionBox : public SharedContext {
|
|||
FunctionBox(JSContext* cx, FunctionBox* traceListHead, SourceExtent extent,
|
||||
CompilationInfo& compilationInfo, Directives directives,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
const ParserAtom* explicitName, FunctionFlags flags,
|
||||
FunctionIndex index, TopLevelFunction isTopLevel);
|
||||
JSAtom* explicitName, FunctionFlags flags, FunctionIndex index,
|
||||
TopLevelFunction isTopLevel);
|
||||
|
||||
MutableHandle<ScriptStencil> functionStencil() const;
|
||||
|
||||
|
@ -439,21 +421,22 @@ class FunctionBox : public SharedContext {
|
|||
bool atomsAreKept();
|
||||
#endif
|
||||
|
||||
ParserLexicalScopeData* namedLambdaBindings() { return namedLambdaBindings_; }
|
||||
void setNamedLambdaBindings(ParserLexicalScopeData* bindings) {
|
||||
namedLambdaBindings_ = bindings;
|
||||
MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
|
||||
MOZ_ASSERT(atomsAreKept());
|
||||
return MutableHandle<LexicalScope::Data*>::fromMarkedLocation(
|
||||
&namedLambdaBindings_);
|
||||
}
|
||||
|
||||
ParserFunctionScopeData* functionScopeBindings() {
|
||||
return functionScopeBindings_;
|
||||
}
|
||||
void setFunctionScopeBindings(ParserFunctionScopeData* bindings) {
|
||||
functionScopeBindings_ = bindings;
|
||||
MutableHandle<FunctionScope::Data*> functionScopeBindings() {
|
||||
MOZ_ASSERT(atomsAreKept());
|
||||
return MutableHandle<FunctionScope::Data*>::fromMarkedLocation(
|
||||
&functionScopeBindings_);
|
||||
}
|
||||
|
||||
ParserVarScopeData* extraVarScopeBindings() { return extraVarScopeBindings_; }
|
||||
void setExtraVarScopeBindings(ParserVarScopeData* bindings) {
|
||||
extraVarScopeBindings_ = bindings;
|
||||
MutableHandle<VarScope::Data*> extraVarScopeBindings() {
|
||||
MOZ_ASSERT(atomsAreKept());
|
||||
return MutableHandle<VarScope::Data*>::fromMarkedLocation(
|
||||
&extraVarScopeBindings_);
|
||||
}
|
||||
|
||||
void initFromLazyFunction(JSFunction* fun);
|
||||
|
@ -570,22 +553,22 @@ class FunctionBox : public SharedContext {
|
|||
bool hasInferredName() const { return flags_.hasInferredName(); }
|
||||
bool hasGuessedAtom() const { return flags_.hasGuessedAtom(); }
|
||||
|
||||
const ParserAtom* displayAtom() const { return atom_; }
|
||||
const ParserAtom* explicitName() const {
|
||||
JSAtom* displayAtom() const { return atom_; }
|
||||
JSAtom* explicitName() const {
|
||||
return (hasInferredName() || hasGuessedAtom()) ? nullptr : atom_;
|
||||
}
|
||||
|
||||
// NOTE: We propagate to any existing functions for now. This handles both the
|
||||
// delazification case where functions already exist, and also handles
|
||||
// code-coverage which is not yet deferred.
|
||||
void setInferredName(const ParserAtom* atom) {
|
||||
void setInferredName(JSAtom* atom) {
|
||||
atom_ = atom;
|
||||
flags_.setInferredName();
|
||||
if (isFunctionFieldCopiedToStencil) {
|
||||
copyUpdatedAtomAndFlags();
|
||||
}
|
||||
}
|
||||
void setGuessedAtom(const ParserAtom* atom) {
|
||||
void setGuessedAtom(JSAtom* atom) {
|
||||
atom_ = atom;
|
||||
flags_.setGuessedAtom();
|
||||
if (isFunctionFieldCopiedToStencil) {
|
||||
|
|
|
@ -120,8 +120,46 @@ Scope* ScopeStencil::createScope(JSContext* cx,
|
|||
}
|
||||
|
||||
void ScopeStencil::trace(JSTracer* trc) {
|
||||
// NOTE: Scope::Data fields such as `canonicalFunction` are always nullptr
|
||||
// while owned by a ScopeStencil so no additional tracing is needed.
|
||||
// Trace Datas
|
||||
if (data_) {
|
||||
switch (kind()) {
|
||||
case ScopeKind::Function: {
|
||||
data<FunctionScope>().trace(trc);
|
||||
break;
|
||||
}
|
||||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical:
|
||||
case ScopeKind::ClassBody: {
|
||||
data<LexicalScope>().trace(trc);
|
||||
break;
|
||||
}
|
||||
case ScopeKind::FunctionBodyVar: {
|
||||
data<VarScope>().trace(trc);
|
||||
break;
|
||||
}
|
||||
case ScopeKind::Global:
|
||||
case ScopeKind::NonSyntactic: {
|
||||
data<GlobalScope>().trace(trc);
|
||||
break;
|
||||
}
|
||||
case ScopeKind::Eval:
|
||||
case ScopeKind::StrictEval: {
|
||||
data<EvalScope>().trace(trc);
|
||||
break;
|
||||
}
|
||||
case ScopeKind::Module: {
|
||||
data<ModuleScope>().trace(trc);
|
||||
break;
|
||||
}
|
||||
case ScopeKind::With:
|
||||
default:
|
||||
MOZ_CRASH("Unexpected data type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ScopeStencil::nextFrameSlot() const {
|
||||
|
@ -159,7 +197,20 @@ uint32_t ScopeStencil::nextFrameSlot() const {
|
|||
MOZ_CRASH("Not an enclosing intra-frame scope");
|
||||
}
|
||||
|
||||
void StencilModuleEntry::trace(JSTracer* trc) {}
|
||||
void StencilModuleEntry::trace(JSTracer* trc) {
|
||||
if (specifier) {
|
||||
TraceManuallyBarrieredEdge(trc, &specifier, "module specifier");
|
||||
}
|
||||
if (localName) {
|
||||
TraceManuallyBarrieredEdge(trc, &localName, "module local name");
|
||||
}
|
||||
if (importName) {
|
||||
TraceManuallyBarrieredEdge(trc, &importName, "module import name");
|
||||
}
|
||||
if (exportName) {
|
||||
TraceManuallyBarrieredEdge(trc, &exportName, "module export name");
|
||||
}
|
||||
}
|
||||
|
||||
void StencilModuleMetadata::trace(JSTracer* trc) {
|
||||
requestedModules.trace(trc);
|
||||
|
@ -169,7 +220,19 @@ void StencilModuleMetadata::trace(JSTracer* trc) {
|
|||
starExportEntries.trace(trc);
|
||||
}
|
||||
|
||||
void ScriptStencil::trace(JSTracer* trc) {}
|
||||
void ScriptStencil::trace(JSTracer* trc) {
|
||||
for (ScriptThingVariant& thing : gcThings) {
|
||||
if (thing.is<ScriptAtom>()) {
|
||||
JSAtom* atom = thing.as<ScriptAtom>();
|
||||
TraceRoot(trc, &atom, "script-atom");
|
||||
MOZ_ASSERT(atom == thing.as<ScriptAtom>(), "Atoms should be unmovable");
|
||||
}
|
||||
}
|
||||
|
||||
if (functionAtom) {
|
||||
TraceRoot(trc, &functionAtom, "script-atom");
|
||||
}
|
||||
}
|
||||
|
||||
static bool CreateLazyScript(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
ScriptStencil& stencil, HandleFunction function) {
|
||||
|
@ -220,14 +283,7 @@ static JSFunction* CreateFunction(JSContext* cx,
|
|||
|
||||
JSNative maybeNative = isAsmJS ? InstantiateAsmJS : nullptr;
|
||||
|
||||
RootedAtom displayAtom(cx);
|
||||
if (stencil.functionAtom) {
|
||||
displayAtom.set(
|
||||
compilationInfo.liftParserAtomToJSAtom(stencil.functionAtom));
|
||||
if (!displayAtom) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
RootedAtom displayAtom(cx, stencil.functionAtom);
|
||||
RootedFunction fun(
|
||||
cx, NewFunctionWithProto(cx, maybeNative, stencil.nargs,
|
||||
stencil.functionFlags, nullptr, displayAtom,
|
||||
|
@ -291,7 +347,7 @@ static bool MaybeInstantiateModule(JSContext* cx,
|
|||
}
|
||||
|
||||
if (!compilationInfo.moduleMetadata.get().initModule(
|
||||
cx, compilationInfo, compilationInfo.module)) {
|
||||
cx, compilationInfo.module)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -459,7 +515,7 @@ static bool InstantiateTopLevel(JSContext* cx,
|
|||
// to update it with information determined by the BytecodeEmitter. This applies
|
||||
// to both initial and delazification parses. The functions being update may or
|
||||
// may not have bytecode at this point.
|
||||
static bool UpdateEmittedInnerFunctions(CompilationInfo& compilationInfo) {
|
||||
static void UpdateEmittedInnerFunctions(CompilationInfo& compilationInfo) {
|
||||
for (auto item : compilationInfo.functionScriptStencils()) {
|
||||
auto& stencil = item.stencil;
|
||||
auto& fun = item.function;
|
||||
|
@ -489,24 +545,15 @@ static bool UpdateEmittedInnerFunctions(CompilationInfo& compilationInfo) {
|
|||
// Inferred and Guessed names are computed by BytecodeEmitter and so may
|
||||
// need to be applied to existing JSFunctions during delazification.
|
||||
if (fun->displayAtom() == nullptr) {
|
||||
JSAtom* funcAtom = nullptr;
|
||||
if (stencil.functionFlags.hasInferredName() ||
|
||||
stencil.functionFlags.hasGuessedAtom()) {
|
||||
funcAtom = compilationInfo.liftParserAtomToJSAtom(stencil.functionAtom);
|
||||
if (!funcAtom) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (stencil.functionFlags.hasInferredName()) {
|
||||
fun->setInferredName(funcAtom);
|
||||
fun->setInferredName(stencil.functionAtom);
|
||||
}
|
||||
|
||||
if (stencil.functionFlags.hasGuessedAtom()) {
|
||||
fun->setGuessedAtom(funcAtom);
|
||||
fun->setGuessedAtom(stencil.functionAtom);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// During initial parse we must link lazy-functions-inside-lazy-functions to
|
||||
|
@ -593,9 +640,7 @@ bool CompilationInfo::instantiateStencils() {
|
|||
|
||||
// Must be infallible from here forward.
|
||||
|
||||
if (!UpdateEmittedInnerFunctions(*this)) {
|
||||
return false;
|
||||
}
|
||||
UpdateEmittedInnerFunctions(*this);
|
||||
|
||||
if (lazy == nullptr) {
|
||||
LinkEnclosingLazyScript(*this);
|
||||
|
@ -714,12 +759,12 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
|
||||
json.beginObjectProperty("data");
|
||||
|
||||
AbstractTrailingNamesArray<const ParserAtom>* trailingNames = nullptr;
|
||||
AbstractTrailingNamesArray<JSAtom>* trailingNames = nullptr;
|
||||
uint32_t length = 0;
|
||||
|
||||
switch (kind_) {
|
||||
case ScopeKind::Function: {
|
||||
auto* data = static_cast<ParserFunctionScopeData*>(data_);
|
||||
auto* data = static_cast<FunctionScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
json.property("hasParameterExprs", data->hasParameterExprs);
|
||||
json.property("nonPositionalFormalStart", data->nonPositionalFormalStart);
|
||||
|
@ -731,7 +776,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
}
|
||||
|
||||
case ScopeKind::FunctionBodyVar: {
|
||||
auto* data = static_cast<ParserVarScopeData*>(data_);
|
||||
auto* data = static_cast<VarScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
|
||||
trailingNames = &data->trailingNames;
|
||||
|
@ -746,7 +791,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical:
|
||||
case ScopeKind::ClassBody: {
|
||||
auto* data = static_cast<ParserLexicalScopeData*>(data_);
|
||||
auto* data = static_cast<LexicalScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
json.property("constStart", data->constStart);
|
||||
|
||||
|
@ -761,7 +806,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
|
||||
case ScopeKind::Eval:
|
||||
case ScopeKind::StrictEval: {
|
||||
auto* data = static_cast<ParserEvalScopeData*>(data_);
|
||||
auto* data = static_cast<EvalScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
|
||||
trailingNames = &data->trailingNames;
|
||||
|
@ -771,7 +816,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
|
||||
case ScopeKind::Global:
|
||||
case ScopeKind::NonSyntactic: {
|
||||
auto* data = static_cast<ParserGlobalScopeData*>(data_);
|
||||
auto* data = static_cast<GlobalScope::Data*>(data_.get());
|
||||
json.property("letStart", data->letStart);
|
||||
json.property("constStart", data->constStart);
|
||||
|
||||
|
@ -781,7 +826,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
}
|
||||
|
||||
case ScopeKind::Module: {
|
||||
auto* data = static_cast<ParserModuleScopeData*>(data_);
|
||||
auto* data = static_cast<ModuleScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
json.property("varStart", data->varStart);
|
||||
json.property("letStart", data->letStart);
|
||||
|
@ -793,9 +838,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
}
|
||||
|
||||
case ScopeKind::WasmInstance: {
|
||||
auto* data =
|
||||
static_cast<AbstractScopeData<WasmInstanceScope, const ParserAtom>*>(
|
||||
data_);
|
||||
auto* data = static_cast<WasmInstanceScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
json.property("globalsStart", data->globalsStart);
|
||||
|
||||
|
@ -805,9 +848,7 @@ void ScopeStencil::dumpFields(js::JSONPrinter& json) {
|
|||
}
|
||||
|
||||
case ScopeKind::WasmFunction: {
|
||||
auto* data =
|
||||
static_cast<AbstractScopeData<WasmFunctionScope, const ParserAtom>*>(
|
||||
data_);
|
||||
auto* data = static_cast<WasmFunctionScope::Data*>(data_.get());
|
||||
json.property("nextFrameSlot", data->nextFrameSlot);
|
||||
|
||||
trailingNames = &data->trailingNames;
|
||||
|
@ -1102,7 +1143,7 @@ static void DumpScriptThing(js::JSONPrinter& json, ScriptThingVariant& thing) {
|
|||
void operator()(ScriptAtom& data) {
|
||||
json.beginObject();
|
||||
json.property("type", "ScriptAtom");
|
||||
const ParserAtom* atom = data;
|
||||
JSAtom* atom = data;
|
||||
GenericPrinter& out = json.beginStringProperty("value");
|
||||
atom->dumpCharsNoQuote(out);
|
||||
json.endStringProperty();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "js/GCVariant.h" // GC Support for mozilla::Variant
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "js/RootingAPI.h" // Handle
|
||||
#include "js/TypeDecls.h" // JSContext
|
||||
#include "js/TypeDecls.h" // JSContext,JSAtom,JSFunction
|
||||
#include "js/UniquePtr.h" // js::UniquePtr
|
||||
#include "js/Utility.h" // UniqueTwoByteChars
|
||||
#include "js/Vector.h" // js::Vector
|
||||
|
@ -48,19 +48,6 @@ class ScriptStencil;
|
|||
class RegExpStencil;
|
||||
class BigIntStencil;
|
||||
|
||||
using BaseParserScopeData = AbstractBaseScopeData<const ParserAtom>;
|
||||
|
||||
template <typename Scope>
|
||||
using ParserScopeData = typename Scope::template AbstractData<const ParserAtom>;
|
||||
using ParserGlobalScopeData = ParserScopeData<GlobalScope>;
|
||||
using ParserEvalScopeData = ParserScopeData<EvalScope>;
|
||||
using ParserLexicalScopeData = ParserScopeData<LexicalScope>;
|
||||
using ParserFunctionScopeData = ParserScopeData<FunctionScope>;
|
||||
using ParserModuleScopeData = ParserScopeData<ModuleScope>;
|
||||
using ParserVarScopeData = ParserScopeData<VarScope>;
|
||||
|
||||
using ParserBindingIter = AbstractBindingIter<const ParserAtom>;
|
||||
|
||||
// [SMDOC] Script Stencil (Frontend Representation)
|
||||
//
|
||||
// Stencils are GC object free representations of artifacts created during
|
||||
|
@ -177,16 +164,13 @@ class ScopeStencil {
|
|||
// The list of binding and scope-specific data. Note that the back pointers to
|
||||
// the owning JSFunction / ModuleObject are not set until Stencils are
|
||||
// converted to GC allocations.
|
||||
//
|
||||
// !NOTE! This data is currently allocated on the CompilationInfo::lifoAlloc.
|
||||
// TODO-Stencil: This must outlive the parse for stencil to be useful.
|
||||
BaseParserScopeData* data_;
|
||||
UniquePtr<BaseScopeData> data_;
|
||||
|
||||
public:
|
||||
ScopeStencil(ScopeKind kind, mozilla::Maybe<ScopeIndex> enclosing,
|
||||
uint32_t firstFrameSlot,
|
||||
mozilla::Maybe<uint32_t> numEnvironmentSlots,
|
||||
BaseParserScopeData* data = {},
|
||||
UniquePtr<BaseScopeData> data = {},
|
||||
mozilla::Maybe<FunctionIndex> functionIndex = mozilla::Nothing(),
|
||||
bool isArrow = false)
|
||||
: enclosing_(enclosing),
|
||||
|
@ -195,22 +179,21 @@ class ScopeStencil {
|
|||
numEnvironmentSlots_(numEnvironmentSlots),
|
||||
functionIndex_(functionIndex),
|
||||
isArrow_(isArrow),
|
||||
data_(data) {}
|
||||
data_(std::move(data)) {}
|
||||
|
||||
static bool createForFunctionScope(
|
||||
JSContext* cx, CompilationInfo& compilationInfo,
|
||||
ParserFunctionScopeData* dataArg, bool hasParameterExprs,
|
||||
Handle<FunctionScope::Data*> dataArg, bool hasParameterExprs,
|
||||
bool needsEnvironment, FunctionIndex functionIndex, bool isArrow,
|
||||
mozilla::Maybe<ScopeIndex> enclosing, ScopeIndex* index);
|
||||
|
||||
static bool createForLexicalScope(
|
||||
JSContext* cx, CompilationInfo& compilationInfo, ScopeKind kind,
|
||||
ParserLexicalScopeData* dataArg, uint32_t firstFrameSlot,
|
||||
Handle<LexicalScope::Data*> dataArg, uint32_t firstFrameSlot,
|
||||
mozilla::Maybe<ScopeIndex> enclosing, ScopeIndex* index);
|
||||
|
||||
static bool createForVarScope(JSContext* cx,
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
ScopeKind kind, ParserVarScopeData* dataArg,
|
||||
static bool createForVarScope(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
ScopeKind kind, Handle<VarScope::Data*> dataArg,
|
||||
uint32_t firstFrameSlot, bool needsEnvironment,
|
||||
mozilla::Maybe<ScopeIndex> enclosing,
|
||||
ScopeIndex* index);
|
||||
|
@ -218,18 +201,19 @@ class ScopeStencil {
|
|||
static bool createForGlobalScope(JSContext* cx,
|
||||
CompilationInfo& compilationInfo,
|
||||
ScopeKind kind,
|
||||
ParserGlobalScopeData* dataArg,
|
||||
Handle<GlobalScope::Data*> dataArg,
|
||||
ScopeIndex* index);
|
||||
|
||||
static bool createForEvalScope(JSContext* cx,
|
||||
CompilationInfo& compilationInfo,
|
||||
ScopeKind kind, ParserEvalScopeData* dataArg,
|
||||
ScopeKind kind,
|
||||
Handle<EvalScope::Data*> dataArg,
|
||||
mozilla::Maybe<ScopeIndex> enclosing,
|
||||
ScopeIndex* index);
|
||||
|
||||
static bool createForModuleScope(JSContext* cx,
|
||||
CompilationInfo& compilationInfo,
|
||||
ParserModuleScopeData* dataArg,
|
||||
Handle<ModuleScope::Data*> dataArg,
|
||||
mozilla::Maybe<ScopeIndex> enclosing,
|
||||
ScopeIndex* index);
|
||||
|
||||
|
@ -266,19 +250,15 @@ class ScopeStencil {
|
|||
private:
|
||||
// Non owning reference to data
|
||||
template <typename SpecificScopeType>
|
||||
typename SpecificScopeType::template AbstractData<const ParserAtom>& data()
|
||||
const {
|
||||
using Data =
|
||||
typename SpecificScopeType ::template AbstractData<const ParserAtom>;
|
||||
|
||||
MOZ_ASSERT(data_);
|
||||
return *static_cast<Data*>(data_);
|
||||
typename SpecificScopeType::Data& data() const {
|
||||
MOZ_ASSERT(data_.get());
|
||||
return *static_cast<typename SpecificScopeType::Data*>(data_.get());
|
||||
}
|
||||
|
||||
// Transfer ownership into a new UniquePtr.
|
||||
template <typename SpecificScopeType>
|
||||
UniquePtr<typename SpecificScopeType::Data> createSpecificScopeData(
|
||||
JSContext* cx, CompilationInfo& compilationInfo);
|
||||
UniquePtr<typename SpecificScopeType::Data> releaseData(
|
||||
CompilationInfo& compilationInfo);
|
||||
|
||||
template <typename SpecificScopeType>
|
||||
uint32_t nextFrameSlot() const {
|
||||
|
@ -322,10 +302,10 @@ class StencilModuleEntry {
|
|||
// localName | null | required | required | nullptr |
|
||||
// importName | null | required | nullptr | required |
|
||||
// exportName | null | null | required | optional |
|
||||
const ParserAtom* specifier = nullptr;
|
||||
const ParserAtom* localName = nullptr;
|
||||
const ParserAtom* importName = nullptr;
|
||||
const ParserAtom* exportName = nullptr;
|
||||
JSAtom* specifier = nullptr;
|
||||
JSAtom* localName = nullptr;
|
||||
JSAtom* importName = nullptr;
|
||||
JSAtom* exportName = nullptr;
|
||||
|
||||
// Location used for error messages. If this is for a module request entry
|
||||
// then it is the module specifier string, otherwise the import/export spec
|
||||
|
@ -339,18 +319,17 @@ class StencilModuleEntry {
|
|||
: lineno(lineno), column(column) {}
|
||||
|
||||
public:
|
||||
static StencilModuleEntry moduleRequest(const ParserAtom* specifier,
|
||||
uint32_t lineno, uint32_t column) {
|
||||
static StencilModuleEntry moduleRequest(JSAtom* specifier, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
MOZ_ASSERT(specifier);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
entry.specifier = specifier;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static StencilModuleEntry importEntry(const ParserAtom* specifier,
|
||||
const ParserAtom* localName,
|
||||
const ParserAtom* importName,
|
||||
uint32_t lineno, uint32_t column) {
|
||||
static StencilModuleEntry importEntry(JSAtom* specifier, JSAtom* localName,
|
||||
JSAtom* importName, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
MOZ_ASSERT(specifier && localName && importName);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
entry.specifier = specifier;
|
||||
|
@ -359,8 +338,7 @@ class StencilModuleEntry {
|
|||
return entry;
|
||||
}
|
||||
|
||||
static StencilModuleEntry exportAsEntry(const ParserAtom* localName,
|
||||
const ParserAtom* exportName,
|
||||
static StencilModuleEntry exportAsEntry(JSAtom* localName, JSAtom* exportName,
|
||||
uint32_t lineno, uint32_t column) {
|
||||
MOZ_ASSERT(localName && exportName);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
|
@ -369,10 +347,10 @@ class StencilModuleEntry {
|
|||
return entry;
|
||||
}
|
||||
|
||||
static StencilModuleEntry exportFromEntry(const ParserAtom* specifier,
|
||||
const ParserAtom* importName,
|
||||
const ParserAtom* exportName,
|
||||
uint32_t lineno, uint32_t column) {
|
||||
static StencilModuleEntry exportFromEntry(JSAtom* specifier,
|
||||
JSAtom* importName,
|
||||
JSAtom* exportName, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
// NOTE: The `export * from "mod";` syntax generates nullptr exportName.
|
||||
MOZ_ASSERT(specifier && importName);
|
||||
StencilModuleEntry entry(lineno, column);
|
||||
|
@ -407,8 +385,7 @@ class StencilModuleMetadata {
|
|||
starExportEntries(cx),
|
||||
functionDecls(cx) {}
|
||||
|
||||
bool initModule(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
JS::Handle<ModuleObject*> module);
|
||||
bool initModule(JSContext* cx, JS::Handle<ModuleObject*> module);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
|
@ -420,10 +397,9 @@ class StencilModuleMetadata {
|
|||
};
|
||||
|
||||
// The lazy closed-over-binding info is represented by these types that will
|
||||
// convert to a nullptr.
|
||||
// convert to a GCCellPtr(nullptr), GCCellPtr(JSAtom*).
|
||||
class NullScriptThing {};
|
||||
|
||||
using ScriptAtom = const ParserAtom*;
|
||||
using ScriptAtom = JSAtom*;
|
||||
|
||||
// These types all end up being baked into GC things as part of stencil
|
||||
// instantiation.
|
||||
|
@ -467,7 +443,7 @@ class ScriptStencil {
|
|||
|
||||
// The explicit or implicit name of the function. The FunctionFlags indicate
|
||||
// the kind of name.
|
||||
const ParserAtom* functionAtom = nullptr;
|
||||
JSAtom* functionAtom = nullptr;
|
||||
|
||||
// See: `FunctionFlags`.
|
||||
FunctionFlags functionFlags = {};
|
||||
|
|
|
@ -122,7 +122,7 @@ bool SwitchEmitter::emitDiscriminant(const Maybe<uint32_t>& switchPos) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SwitchEmitter::emitLexical(ParserLexicalScopeData* bindings) {
|
||||
bool SwitchEmitter::emitLexical(Handle<LexicalScope::Data*> bindings) {
|
||||
MOZ_ASSERT(state_ == State::Discriminant);
|
||||
MOZ_ASSERT(bindings);
|
||||
|
||||
|
|
|
@ -441,7 +441,7 @@ class MOZ_STACK_CLASS SwitchEmitter {
|
|||
|
||||
// `bindings` is a lexical scope for the entire switch, in case there's
|
||||
// let/const effectively directly under case or default blocks.
|
||||
MOZ_MUST_USE bool emitLexical(ParserLexicalScopeData* bindings);
|
||||
MOZ_MUST_USE bool emitLexical(Handle<LexicalScope::Data*> bindings);
|
||||
|
||||
MOZ_MUST_USE bool emitCond();
|
||||
MOZ_MUST_USE bool emitTable(const TableGenerator& tableGen);
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace frontend {
|
|||
// amounts of code that never executes (which happens often).
|
||||
class SyntaxParseHandler {
|
||||
// Remember the last encountered name or string literal during syntax parses.
|
||||
const ParserAtom* lastAtom;
|
||||
JSAtom* lastAtom;
|
||||
TokenPos lastStringPos;
|
||||
|
||||
// WARNING: Be careful about adding fields to this function, that might be
|
||||
|
@ -192,8 +192,7 @@ class SyntaxParseHandler {
|
|||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
||||
#undef DECLARE_AS
|
||||
|
||||
NameNodeType newName(const ParserName* name, const TokenPos& pos,
|
||||
JSContext* cx) {
|
||||
NameNodeType newName(PropertyName* name, const TokenPos& pos, JSContext* cx) {
|
||||
lastAtom = name;
|
||||
if (name == cx->parserNames().arguments) {
|
||||
return NodeArgumentsName;
|
||||
|
@ -212,12 +211,11 @@ class SyntaxParseHandler {
|
|||
return NodeGeneric;
|
||||
}
|
||||
|
||||
NameNodeType newObjectLiteralPropertyName(const ParserAtom* atom,
|
||||
const TokenPos& pos) {
|
||||
NameNodeType newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
|
||||
return NodeName;
|
||||
}
|
||||
|
||||
NameNodeType newPrivateName(const ParserAtom* atom, const TokenPos& pos) {
|
||||
NameNodeType newPrivateName(JSAtom* atom, const TokenPos& pos) {
|
||||
return NodePrivateName;
|
||||
}
|
||||
|
||||
|
@ -232,14 +230,13 @@ class SyntaxParseHandler {
|
|||
return NodeGeneric;
|
||||
}
|
||||
|
||||
NameNodeType newStringLiteral(const ParserAtom* atom, const TokenPos& pos) {
|
||||
NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) {
|
||||
lastAtom = atom;
|
||||
lastStringPos = pos;
|
||||
return NodeUnparenthesizedString;
|
||||
}
|
||||
|
||||
NameNodeType newTemplateStringLiteral(const ParserAtom* atom,
|
||||
const TokenPos& pos) {
|
||||
NameNodeType newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
|
@ -461,11 +458,11 @@ class SyntaxParseHandler {
|
|||
CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
ContinueStatementType newContinueStatement(const ParserName* label,
|
||||
ContinueStatementType newContinueStatement(PropertyName* label,
|
||||
const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
BreakStatementType newBreakStatement(const ParserName* label,
|
||||
BreakStatementType newBreakStatement(PropertyName* label,
|
||||
const TokenPos& pos) {
|
||||
return NodeBreak;
|
||||
}
|
||||
|
@ -477,7 +474,7 @@ class SyntaxParseHandler {
|
|||
return NodeGeneric;
|
||||
}
|
||||
|
||||
LabeledStatementType newLabeledStatement(const ParserName* label, Node stmt,
|
||||
LabeledStatementType newLabeledStatement(PropertyName* label, Node stmt,
|
||||
uint32_t begin) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
@ -494,7 +491,7 @@ class SyntaxParseHandler {
|
|||
return NodeGeneric;
|
||||
}
|
||||
|
||||
NameNodeType newPropertyName(const ParserName* name, const TokenPos& pos) {
|
||||
NameNodeType newPropertyName(PropertyName* name, const TokenPos& pos) {
|
||||
lastAtom = name;
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
@ -703,7 +700,7 @@ class SyntaxParseHandler {
|
|||
bool isPrivateName(Node node) { return node == NodePrivateName; }
|
||||
bool isPrivateField(Node node) { return node == NodePrivateElement; }
|
||||
|
||||
const ParserName* maybeDottedProperty(Node node) {
|
||||
PropertyName* maybeDottedProperty(Node node) {
|
||||
// Note: |super.apply(...)| is a special form that calls an "apply"
|
||||
// method retrieved from one value, but using a *different* value as
|
||||
// |this|. It's not really eligible for the funapply/funcall
|
||||
|
@ -712,10 +709,10 @@ class SyntaxParseHandler {
|
|||
if (node != NodeDottedProperty && node != NodeOptionalDottedProperty) {
|
||||
return nullptr;
|
||||
}
|
||||
return lastAtom->asName();
|
||||
return lastAtom->asPropertyName();
|
||||
}
|
||||
|
||||
const ParserAtom* isStringExprStatement(Node pn, TokenPos* pos) {
|
||||
JSAtom* isStringExprStatement(Node pn, TokenPos* pos) {
|
||||
if (pn == NodeStringExprStatement) {
|
||||
*pos = lastStringPos;
|
||||
return lastAtom;
|
||||
|
|
|
@ -24,7 +24,7 @@ bool TDZCheckCache::ensureCache(BytecodeEmitter* bce) {
|
|||
}
|
||||
|
||||
Maybe<MaybeCheckTDZ> TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce,
|
||||
const ParserAtom* name) {
|
||||
JSAtom* name) {
|
||||
if (!ensureCache(bce)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ Maybe<MaybeCheckTDZ> TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce,
|
|||
return Some(rv);
|
||||
}
|
||||
|
||||
bool TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
bool TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
|
||||
MaybeCheckTDZ check) {
|
||||
if (!ensureCache(bce)) {
|
||||
return false;
|
||||
|
|
|
@ -47,8 +47,8 @@ class TDZCheckCache : public Nestable<TDZCheckCache> {
|
|||
explicit TDZCheckCache(BytecodeEmitter* bce);
|
||||
|
||||
mozilla::Maybe<MaybeCheckTDZ> needsTDZCheck(BytecodeEmitter* bce,
|
||||
const ParserAtom* name);
|
||||
MOZ_MUST_USE bool noteTDZCheck(BytecodeEmitter* bce, const ParserAtom* name,
|
||||
JSAtom* name);
|
||||
MOZ_MUST_USE bool noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
|
||||
MaybeCheckTDZ check);
|
||||
};
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
#include <stdint.h> // uint32_t
|
||||
|
||||
#include "frontend/ParserAtom.h" // js::frontend::{ParserAtom,ParserName}
|
||||
#include "frontend/TokenKind.h" // js::frontend::TokenKind
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "vm/StringType.h" // js::PropertyName
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -144,10 +144,10 @@ struct Token {
|
|||
friend struct Token;
|
||||
|
||||
/** Non-numeric atom. */
|
||||
const ParserName* name;
|
||||
PropertyName* name;
|
||||
|
||||
/** Potentially-numeric atom. */
|
||||
const ParserAtom* atom;
|
||||
JSAtom* atom;
|
||||
|
||||
struct {
|
||||
/** Numeric literal's value. */
|
||||
|
@ -168,12 +168,12 @@ struct Token {
|
|||
|
||||
// Mutators
|
||||
|
||||
void setName(const ParserName* name) {
|
||||
void setName(PropertyName* name) {
|
||||
MOZ_ASSERT(type == TokenKind::Name || type == TokenKind::PrivateName);
|
||||
u.name = name;
|
||||
}
|
||||
|
||||
void setAtom(const ParserAtom* atom) {
|
||||
void setAtom(JSAtom* atom) {
|
||||
MOZ_ASSERT(type == TokenKind::String || type == TokenKind::TemplateHead ||
|
||||
type == TokenKind::NoSubsTemplate);
|
||||
u.atom = atom;
|
||||
|
@ -192,12 +192,12 @@ struct Token {
|
|||
|
||||
// Type-safe accessors
|
||||
|
||||
const ParserName* name() const {
|
||||
PropertyName* name() const {
|
||||
MOZ_ASSERT(type == TokenKind::Name || type == TokenKind::PrivateName);
|
||||
return u.name->asName(); // poor-man's type verification
|
||||
return u.name->JSAtom::asPropertyName(); // poor-man's type verification
|
||||
}
|
||||
|
||||
const ParserAtom* atom() const {
|
||||
JSAtom* atom() const {
|
||||
MOZ_ASSERT(type == TokenKind::String || type == TokenKind::TemplateHead ||
|
||||
type == TokenKind::NoSubsTemplate);
|
||||
return u.atom;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "frontend/ReservedWords.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
|
@ -126,34 +125,28 @@ MOZ_ALWAYS_INLINE const ReservedWordInfo* FindReservedWord<Utf8Unit>(
|
|||
return FindReservedWord(Utf8AsUnsignedChars(units), length);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
static const ReservedWordInfo* FindReservedWord(
|
||||
const CharT* chars, size_t length,
|
||||
js::frontend::NameVisibility* visibility) {
|
||||
JSLinearString* str, js::frontend::NameVisibility* visibility) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (str->hasLatin1Chars()) {
|
||||
const JS::Latin1Char* chars = str->latin1Chars(nogc);
|
||||
size_t length = str->length();
|
||||
if (length > 0 && chars[0] == '#') {
|
||||
*visibility = js::frontend::NameVisibility::Private;
|
||||
return nullptr;
|
||||
}
|
||||
*visibility = js::frontend::NameVisibility::Public;
|
||||
return FindReservedWord(chars, length);
|
||||
}
|
||||
|
||||
static const ReservedWordInfo* FindReservedWord(
|
||||
JSLinearString* str, js::frontend::NameVisibility* visibility) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (str->hasLatin1Chars()) {
|
||||
return FindReservedWord(str->latin1Chars(nogc), str->length(), visibility);
|
||||
}
|
||||
return FindReservedWord(str->twoByteChars(nogc), str->length(), visibility);
|
||||
}
|
||||
|
||||
static const ReservedWordInfo* FindReservedWord(
|
||||
const js::frontend::ParserAtomEntry* atom,
|
||||
js::frontend::NameVisibility* visibility) {
|
||||
if (atom->hasLatin1Chars()) {
|
||||
return FindReservedWord(atom->latin1Chars(), atom->length(), visibility);
|
||||
const char16_t* chars = str->twoByteChars(nogc);
|
||||
size_t length = str->length();
|
||||
if (length > 0 && chars[0] == '#') {
|
||||
*visibility = js::frontend::NameVisibility::Private;
|
||||
return nullptr;
|
||||
}
|
||||
return FindReservedWord(atom->twoByteChars(), atom->length(), visibility);
|
||||
*visibility = js::frontend::NameVisibility::Public;
|
||||
return FindReservedWord(chars, length);
|
||||
}
|
||||
|
||||
static uint32_t GetSingleCodePoint(const char16_t** p, const char16_t* end) {
|
||||
|
@ -207,12 +200,6 @@ bool IsIdentifier(JSLinearString* str) {
|
|||
}
|
||||
return IsIdentifier(str->twoByteChars(nogc), str->length());
|
||||
}
|
||||
bool IsIdentifier(const ParserAtom* atom) {
|
||||
MOZ_ASSERT(atom);
|
||||
return atom->hasLatin1Chars()
|
||||
? IsIdentifier(atom->latin1Chars(), atom->length())
|
||||
: IsIdentifier(atom->twoByteChars(), atom->length());
|
||||
}
|
||||
|
||||
bool IsIdentifierNameOrPrivateName(JSLinearString* str) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
@ -222,12 +209,6 @@ bool IsIdentifierNameOrPrivateName(JSLinearString* str) {
|
|||
}
|
||||
return IsIdentifierNameOrPrivateName(str->twoByteChars(nogc), str->length());
|
||||
}
|
||||
bool IsIdentifierNameOrPrivateName(const ParserAtom* atom) {
|
||||
if (atom->hasLatin1Chars()) {
|
||||
return IsIdentifierNameOrPrivateName(atom->latin1Chars(), atom->length());
|
||||
}
|
||||
return IsIdentifierNameOrPrivateName(atom->twoByteChars(), atom->length());
|
||||
}
|
||||
|
||||
bool IsIdentifier(const Latin1Char* chars, size_t length) {
|
||||
if (length == 0) {
|
||||
|
@ -321,14 +302,6 @@ bool IsIdentifierNameOrPrivateName(const char16_t* chars, size_t length) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IsKeyword(const ParserAtom* atom) {
|
||||
NameVisibility visibility;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(atom, &visibility)) {
|
||||
return TokenKindIsKeyword(rw->tokentype);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool IsKeyword(JSLinearString* str) {
|
||||
NameVisibility visibility;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str, &visibility)) {
|
||||
|
@ -338,9 +311,9 @@ bool IsKeyword(JSLinearString* str) {
|
|||
return false;
|
||||
}
|
||||
|
||||
TokenKind ReservedWordTokenKind(const ParserName* name) {
|
||||
TokenKind ReservedWordTokenKind(PropertyName* str) {
|
||||
NameVisibility visibility;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(name, &visibility)) {
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str, &visibility)) {
|
||||
return rw->tokentype;
|
||||
}
|
||||
|
||||
|
@ -348,9 +321,9 @@ TokenKind ReservedWordTokenKind(const ParserName* name) {
|
|||
: TokenKind::Name;
|
||||
}
|
||||
|
||||
const char* ReservedWordToCharZ(const ParserName* name) {
|
||||
const char* ReservedWordToCharZ(PropertyName* str) {
|
||||
NameVisibility visibility;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(name, &visibility)) {
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str, &visibility)) {
|
||||
return ReservedWordToCharZ(rw->tokentype);
|
||||
}
|
||||
|
||||
|
@ -371,7 +344,7 @@ const char* ReservedWordToCharZ(TokenKind tt) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const ParserName* TokenStreamAnyChars::reservedWordToPropertyName(
|
||||
PropertyName* TokenStreamAnyChars::reservedWordToPropertyName(
|
||||
TokenKind tt) const {
|
||||
MOZ_ASSERT(tt != TokenKind::Name);
|
||||
switch (tt) {
|
||||
|
@ -2251,7 +2224,7 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::identifierName(
|
|||
}
|
||||
}
|
||||
|
||||
const ParserAtom* atom = nullptr;
|
||||
JSAtom* atom;
|
||||
if (MOZ_UNLIKELY(escaping == IdentifierEscapes::SawUnicodeEscape)) {
|
||||
// Identifiers containing Unicode escapes have to be converted into
|
||||
// tokenbuf before atomizing.
|
||||
|
@ -2283,10 +2256,10 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::identifierName(
|
|||
|
||||
noteBadToken.release();
|
||||
if (visibility == NameVisibility::Private) {
|
||||
newPrivateNameToken(atom->asName(), start, modifier, out);
|
||||
newPrivateNameToken(atom->asPropertyName(), start, modifier, out);
|
||||
return true;
|
||||
}
|
||||
newNameToken(atom->asName(), start, modifier, out);
|
||||
newNameToken(atom->asPropertyName(), start, modifier, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3696,7 +3669,7 @@ bool TokenStreamSpecific<Unit, AnyCharsAccess>::getStringOrTemplateToken(
|
|||
}
|
||||
}
|
||||
|
||||
const ParserAtom* atom = drainCharBufferIntoAtom();
|
||||
JSAtom* atom = drainCharBufferIntoAtom();
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -205,7 +205,6 @@
|
|||
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "frontend/ErrorReporter.h"
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "frontend/Token.h"
|
||||
#include "frontend/TokenKind.h"
|
||||
#include "js/CompileOptions.h"
|
||||
|
@ -228,9 +227,9 @@ class AutoKeepAtoms;
|
|||
|
||||
namespace frontend {
|
||||
|
||||
extern TokenKind ReservedWordTokenKind(const ParserName* name);
|
||||
extern TokenKind ReservedWordTokenKind(PropertyName* str);
|
||||
|
||||
extern const char* ReservedWordToCharZ(const ParserName* name);
|
||||
extern const char* ReservedWordToCharZ(PropertyName* str);
|
||||
|
||||
extern const char* ReservedWordToCharZ(TokenKind tt);
|
||||
|
||||
|
@ -731,10 +730,10 @@ class TokenStreamAnyChars : public TokenStreamShared {
|
|||
MOZ_MUST_USE bool checkOptions();
|
||||
|
||||
private:
|
||||
const ParserName* reservedWordToPropertyName(TokenKind tt) const;
|
||||
PropertyName* reservedWordToPropertyName(TokenKind tt) const;
|
||||
|
||||
public:
|
||||
const ParserName* currentName() const {
|
||||
PropertyName* currentName() const {
|
||||
if (isCurrentTokenType(TokenKind::Name) ||
|
||||
isCurrentTokenType(TokenKind::PrivateName)) {
|
||||
return currentToken().name();
|
||||
|
@ -748,8 +747,7 @@ class TokenStreamAnyChars : public TokenStreamShared {
|
|||
if (isCurrentTokenType(TokenKind::Name) ||
|
||||
isCurrentTokenType(TokenKind::PrivateName)) {
|
||||
TokenPos pos = currentToken().pos;
|
||||
const ParserAtom* name = currentToken().name();
|
||||
return (pos.end - pos.begin) != name->length();
|
||||
return (pos.end - pos.begin) != currentToken().name()->length();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
|
||||
|
@ -1539,16 +1537,24 @@ class TokenStreamCharsShared {
|
|||
return mozilla::IsAscii(static_cast<char32_t>(unit));
|
||||
}
|
||||
|
||||
const ParserAtom* drainCharBufferIntoAtom() {
|
||||
JSAtom* drainCharBufferIntoAtom() {
|
||||
JSAtom* atom = AtomizeChars(this->compilationInfo->cx, charBuffer.begin(),
|
||||
charBuffer.length());
|
||||
if (!atom) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add to parser atoms table.
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
auto maybeId = this->compilationInfo->parserAtoms.internChar16(
|
||||
this->compilationInfo->cx, charBuffer.begin(), charBuffer.length());
|
||||
if (maybeId.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif // JS_PARSER_ATOMS
|
||||
|
||||
charBuffer.clear();
|
||||
return maybeId.unwrap();
|
||||
return atom;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -1609,8 +1615,7 @@ class TokenStreamCharsBase : public TokenStreamCharsShared {
|
|||
sourceUnits.ungetCodeUnit();
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE const ParserAtom* atomizeSourceChars(
|
||||
mozilla::Span<const Unit> units);
|
||||
MOZ_ALWAYS_INLINE JSAtom* atomizeSourceChars(mozilla::Span<const Unit> units);
|
||||
|
||||
/**
|
||||
* Try to match a non-LineTerminator ASCII code point. Return true iff it
|
||||
|
@ -1696,21 +1701,45 @@ inline void TokenStreamCharsBase<Unit>::consumeKnownCodeUnit(int32_t unit) {
|
|||
}
|
||||
|
||||
template <>
|
||||
MOZ_ALWAYS_INLINE const ParserAtom*
|
||||
TokenStreamCharsBase<char16_t>::atomizeSourceChars(
|
||||
MOZ_ALWAYS_INLINE JSAtom* TokenStreamCharsBase<char16_t>::atomizeSourceChars(
|
||||
mozilla::Span<const char16_t> units) {
|
||||
return this->compilationInfo->parserAtoms
|
||||
.internChar16(this->compilationInfo->cx, units.data(), units.size())
|
||||
.unwrapOr(nullptr);
|
||||
JSAtom* atom =
|
||||
AtomizeChars(this->compilationInfo->cx, units.data(), units.size());
|
||||
if (!atom) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
auto maybeId = this->compilationInfo->parserAtoms.internChar16(
|
||||
this->compilationInfo->cx, units.data(), units.size());
|
||||
if (maybeId.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif // JS_PARSER_ATOMS
|
||||
|
||||
return atom;
|
||||
}
|
||||
|
||||
template <>
|
||||
/* static */ MOZ_ALWAYS_INLINE const ParserAtom*
|
||||
/* static */ MOZ_ALWAYS_INLINE JSAtom*
|
||||
TokenStreamCharsBase<mozilla::Utf8Unit>::atomizeSourceChars(
|
||||
mozilla::Span<const mozilla::Utf8Unit> units) {
|
||||
return this->compilationInfo->parserAtoms
|
||||
.internUtf8(this->compilationInfo->cx, units.data(), units.size())
|
||||
.unwrapOr(nullptr);
|
||||
auto chars = ToCharSpan(units);
|
||||
JSAtom* atom =
|
||||
AtomizeUTF8Chars(this->compilationInfo->cx, chars.data(), chars.size());
|
||||
if (!atom) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
auto maybeId = this->compilationInfo->parserAtoms.internUtf8(
|
||||
this->compilationInfo->cx, units.data(), units.size());
|
||||
if (maybeId.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif // JS_PARSER_ATOMS
|
||||
|
||||
return atom;
|
||||
}
|
||||
|
||||
template <typename Unit>
|
||||
|
@ -1994,7 +2023,7 @@ class GeneralTokenStreamChars : public SpecializedTokenStreamCharsBase<Unit> {
|
|||
newToken(TokenKind::BigInt, start, modifier, out);
|
||||
}
|
||||
|
||||
void newAtomToken(TokenKind kind, const ParserAtom* atom, TokenStart start,
|
||||
void newAtomToken(TokenKind kind, JSAtom* atom, TokenStart start,
|
||||
TokenStreamShared::Modifier modifier, TokenKind* out) {
|
||||
MOZ_ASSERT(kind == TokenKind::String || kind == TokenKind::TemplateHead ||
|
||||
kind == TokenKind::NoSubsTemplate);
|
||||
|
@ -2003,13 +2032,13 @@ class GeneralTokenStreamChars : public SpecializedTokenStreamCharsBase<Unit> {
|
|||
token->setAtom(atom);
|
||||
}
|
||||
|
||||
void newNameToken(const ParserName* name, TokenStart start,
|
||||
void newNameToken(PropertyName* name, TokenStart start,
|
||||
TokenStreamShared::Modifier modifier, TokenKind* out) {
|
||||
Token* token = newToken(TokenKind::Name, start, modifier, out);
|
||||
token->setName(name);
|
||||
}
|
||||
|
||||
void newPrivateNameToken(const ParserName* name, TokenStart start,
|
||||
void newPrivateNameToken(PropertyName* name, TokenStart start,
|
||||
TokenStreamShared::Modifier modifier,
|
||||
TokenKind* out) {
|
||||
Token* token = newToken(TokenKind::PrivateName, start, modifier, out);
|
||||
|
@ -2122,7 +2151,7 @@ class GeneralTokenStreamChars : public SpecializedTokenStreamCharsBase<Unit> {
|
|||
*/
|
||||
void consumeOptionalHashbangComment();
|
||||
|
||||
const ParserAtom* getRawTemplateStringAtom() {
|
||||
JSAtom* getRawTemplateStringAtom() {
|
||||
TokenStreamAnyChars& anyChars = anyCharsAccess();
|
||||
|
||||
MOZ_ASSERT(anyChars.currentToken().type == TokenKind::TemplateHead ||
|
||||
|
|
|
@ -96,10 +96,10 @@ namespace frontend {
|
|||
// clang-format on
|
||||
|
||||
struct UnboundPrivateName {
|
||||
const ParserAtom* atom;
|
||||
JSAtom* atom;
|
||||
TokenPos position;
|
||||
|
||||
UnboundPrivateName(const ParserAtom* atom, TokenPos position)
|
||||
UnboundPrivateName(JSAtom* atom, TokenPos position)
|
||||
: atom(atom), position(position) {}
|
||||
};
|
||||
|
||||
|
@ -165,8 +165,7 @@ class UsedNameTracker {
|
|||
mozilla::Maybe<TokenPos> pos() { return firstUsePos_; }
|
||||
};
|
||||
|
||||
using UsedNameMap = HashMap<const ParserAtom*, UsedNameInfo,
|
||||
DefaultHasher<const ParserAtom*>>;
|
||||
using UsedNameMap = HashMap<JSAtom*, UsedNameInfo, DefaultHasher<JSAtom*>>;
|
||||
|
||||
private:
|
||||
// The map of names to chains of uses.
|
||||
|
@ -193,13 +192,11 @@ class UsedNameTracker {
|
|||
return scopeCounter_++;
|
||||
}
|
||||
|
||||
UsedNameMap::Ptr lookup(const ParserAtom* name) const {
|
||||
return map_.lookup(name);
|
||||
}
|
||||
UsedNameMap::Ptr lookup(JSAtom* name) const { return map_.lookup(name); }
|
||||
|
||||
MOZ_MUST_USE bool noteUse(
|
||||
JSContext* cx, const ParserAtom* name, NameVisibility visibility,
|
||||
uint32_t scriptId, uint32_t scopeId,
|
||||
JSContext* cx, JSAtom* name, NameVisibility visbility, uint32_t scriptId,
|
||||
uint32_t scopeId,
|
||||
mozilla::Maybe<TokenPos> tokenPosition = mozilla::Nothing());
|
||||
|
||||
// Fill maybeUnboundName with the first (source order) unbound name, or
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include "jstypes.h"
|
||||
|
||||
#include "double-conversion/double-conversion.h"
|
||||
#include "frontend/CompilationInfo.h" // frontend::CompilationInfo
|
||||
#include "frontend/ParserAtom.h" // frontend::ParserAtom
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/Conversions.h"
|
||||
#if !JS_HAS_INTL_API
|
||||
|
@ -847,23 +845,6 @@ JSAtom* js::Int32ToAtom(JSContext* cx, int32_t si) {
|
|||
return atom;
|
||||
}
|
||||
|
||||
const frontend::ParserAtom* js::Int32ToParserAtom(
|
||||
frontend::CompilationInfo& compilationInfo, int32_t si) {
|
||||
char buffer[JSFatInlineString::MAX_LENGTH_TWO_BYTE + 1];
|
||||
size_t length;
|
||||
char* start = BackfillInt32InBuffer(
|
||||
si, buffer, JSFatInlineString::MAX_LENGTH_TWO_BYTE + 1, &length);
|
||||
|
||||
Maybe<uint32_t> indexValue;
|
||||
if (si >= 0) {
|
||||
indexValue.emplace(si);
|
||||
}
|
||||
|
||||
return compilationInfo.parserAtoms
|
||||
.internAscii(compilationInfo.cx, start, length)
|
||||
.unwrapOr(nullptr);
|
||||
}
|
||||
|
||||
/* Returns a non-nullptr pointer to inside cbuf. */
|
||||
static char* Int32ToCString(ToCStringBuf* cbuf, int32_t i, size_t* len,
|
||||
int base = 10) {
|
||||
|
@ -1650,28 +1631,6 @@ JSAtom* js::NumberToAtom(JSContext* cx, double d) {
|
|||
return atom;
|
||||
}
|
||||
|
||||
const frontend::ParserAtom* js::NumberToParserAtom(
|
||||
frontend::CompilationInfo& compilationInfo, double d) {
|
||||
int32_t si;
|
||||
if (NumberEqualsInt32(d, &si)) {
|
||||
return Int32ToParserAtom(compilationInfo, si);
|
||||
}
|
||||
|
||||
ToCStringBuf cbuf;
|
||||
char* numStr = FracNumberToCString(compilationInfo.cx, &cbuf, d);
|
||||
if (!numStr) {
|
||||
ReportOutOfMemory(compilationInfo.cx);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(!cbuf.dbuf && numStr >= cbuf.sbuf &&
|
||||
numStr < cbuf.sbuf + cbuf.sbufSize);
|
||||
|
||||
size_t length = strlen(numStr);
|
||||
return compilationInfo.parserAtoms
|
||||
.internAscii(compilationInfo.cx, numStr, length)
|
||||
.unwrapOr(nullptr);
|
||||
}
|
||||
|
||||
JSLinearString* js::IndexToString(JSContext* cx, uint32_t index) {
|
||||
if (StaticStrings::hasUint(index)) {
|
||||
return cx->staticStrings().getUint(index);
|
||||
|
|
|
@ -19,13 +19,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
|
||||
struct CompilationInfo;
|
||||
class ParserAtom;
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
class GlobalObject;
|
||||
class StringBuffer;
|
||||
|
||||
|
@ -49,9 +42,6 @@ extern JSString* NumberToStringHelperPure(JSContext* cx, double d);
|
|||
|
||||
extern JSAtom* NumberToAtom(JSContext* cx, double d);
|
||||
|
||||
const frontend::ParserAtom* NumberToParserAtom(
|
||||
frontend::CompilationInfo& compilationInfo, double d);
|
||||
|
||||
template <AllowGC allowGC>
|
||||
extern JSLinearString* Int32ToString(JSContext* cx, int32_t i);
|
||||
|
||||
|
@ -59,9 +49,6 @@ extern JSLinearString* Int32ToStringHelperPure(JSContext* cx, int32_t i);
|
|||
|
||||
extern JSAtom* Int32ToAtom(JSContext* cx, int32_t si);
|
||||
|
||||
const frontend::ParserAtom* Int32ToParserAtom(
|
||||
frontend::CompilationInfo& compilationInfo, int32_t si);
|
||||
|
||||
// ES6 15.7.3.12
|
||||
extern bool IsInteger(const Value& val);
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "frontend/CompilationInfo.h" // frontend::CompilationInfo
|
||||
#include "frontend/ParserAtom.h" // frontend::ParserAtom
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/StringType-inl.h"
|
||||
|
||||
|
@ -76,20 +74,6 @@ bool StringBuffer::inflateChars() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool StringBuffer::append(const frontend::ParserAtom* ent) {
|
||||
if (isLatin1()) {
|
||||
if (ent->hasLatin1Chars()) {
|
||||
return latin1Chars().append(ent->latin1Chars(), ent->length());
|
||||
}
|
||||
if (!inflateChars()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ent->hasLatin1Chars()
|
||||
? twoByteChars().append(ent->latin1Chars(), ent->length())
|
||||
: twoByteChars().append(ent->twoByteChars(), ent->length());
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
JSLinearString* StringBuffer::finishStringInternal(JSContext* cx) {
|
||||
size_t len = length();
|
||||
|
@ -154,32 +138,6 @@ JSAtom* StringBuffer::finishAtom() {
|
|||
return atom;
|
||||
}
|
||||
|
||||
const frontend::ParserAtom* StringBuffer::finishParserAtom(
|
||||
frontend::CompilationInfo& compilationInfo) {
|
||||
size_t len = length();
|
||||
if (len == 0) {
|
||||
return cx_->parserNames().empty;
|
||||
}
|
||||
|
||||
if (isLatin1()) {
|
||||
auto result = compilationInfo.parserAtoms.internLatin1(
|
||||
cx_, latin1Chars().begin(), len);
|
||||
if (result.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
latin1Chars().clear();
|
||||
return result.unwrap();
|
||||
}
|
||||
|
||||
auto result = compilationInfo.parserAtoms.internChar16(
|
||||
cx_, twoByteChars().begin(), len);
|
||||
if (result.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
twoByteChars().clear();
|
||||
return result.unwrap();
|
||||
}
|
||||
|
||||
bool js::ValueToStringBufferSlow(JSContext* cx, const Value& arg,
|
||||
StringBuffer& sb) {
|
||||
RootedValue v(cx, arg);
|
||||
|
|
|
@ -16,13 +16,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
|
||||
class ParserAtom;
|
||||
struct CompilationInfo;
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
class StringBufferAllocPolicy {
|
||||
TempAllocPolicy impl_;
|
||||
|
||||
|
@ -243,7 +236,6 @@ class StringBuffer {
|
|||
size_t len);
|
||||
inline MOZ_MUST_USE bool appendSubstring(JSLinearString* base, size_t off,
|
||||
size_t len);
|
||||
MOZ_MUST_USE bool append(const frontend::ParserAtom* atom);
|
||||
|
||||
MOZ_MUST_USE bool append(const char* chars, size_t len) {
|
||||
return append(reinterpret_cast<const Latin1Char*>(chars), len);
|
||||
|
@ -319,8 +311,6 @@ class StringBuffer {
|
|||
|
||||
/* Identical to finishString() except that an atom is created. */
|
||||
JSAtom* finishAtom();
|
||||
const frontend::ParserAtom* finishParserAtom(
|
||||
frontend::CompilationInfo& compilationInfo);
|
||||
|
||||
/*
|
||||
* Creates a raw string from the characters in this buffer. The string is
|
||||
|
|
|
@ -74,48 +74,43 @@ static bool IsPrototype(BuiltinObjectKind kind) {
|
|||
MOZ_CRASH("Unexpected builtin object kind");
|
||||
}
|
||||
|
||||
using BuiltinName =
|
||||
const js::frontend::ParserName* js::frontend::WellKnownParserAtoms::*;
|
||||
using BuiltinName = js::ImmutablePropertyNamePtr JSAtomState::*;
|
||||
|
||||
struct BuiltinObjectMap {
|
||||
BuiltinName name;
|
||||
BuiltinObjectKind kind;
|
||||
};
|
||||
|
||||
BuiltinObjectKind js::BuiltinConstructorForName(
|
||||
JSContext* cx, const js::frontend::ParserAtom* name) {
|
||||
using WellKnownName = js::frontend::WellKnownParserAtoms;
|
||||
BuiltinObjectKind js::BuiltinConstructorForName(JSContext* cx, JSAtom* name) {
|
||||
static constexpr BuiltinObjectMap constructors[] = {
|
||||
{&WellKnownName::Array, BuiltinObjectKind::Array},
|
||||
{&WellKnownName::ArrayBuffer, BuiltinObjectKind::ArrayBuffer},
|
||||
{&WellKnownName::Iterator, BuiltinObjectKind::Iterator},
|
||||
{&WellKnownName::Promise, BuiltinObjectKind::Promise},
|
||||
{&WellKnownName::RegExp, BuiltinObjectKind::RegExp},
|
||||
{&WellKnownName::SharedArrayBuffer, BuiltinObjectKind::SharedArrayBuffer},
|
||||
{&WellKnownName::DateTimeFormat, BuiltinObjectKind::DateTimeFormat},
|
||||
{&WellKnownName::NumberFormat, BuiltinObjectKind::NumberFormat},
|
||||
{&JSAtomState::Array, BuiltinObjectKind::Array},
|
||||
{&JSAtomState::ArrayBuffer, BuiltinObjectKind::ArrayBuffer},
|
||||
{&JSAtomState::Iterator, BuiltinObjectKind::Iterator},
|
||||
{&JSAtomState::Promise, BuiltinObjectKind::Promise},
|
||||
{&JSAtomState::RegExp, BuiltinObjectKind::RegExp},
|
||||
{&JSAtomState::SharedArrayBuffer, BuiltinObjectKind::SharedArrayBuffer},
|
||||
{&JSAtomState::DateTimeFormat, BuiltinObjectKind::DateTimeFormat},
|
||||
{&JSAtomState::NumberFormat, BuiltinObjectKind::NumberFormat},
|
||||
};
|
||||
|
||||
for (auto& builtin : constructors) {
|
||||
if (name == cx->parserNames().*(builtin.name)) {
|
||||
if (name == cx->names().*(builtin.name)) {
|
||||
return builtin.kind;
|
||||
}
|
||||
}
|
||||
return BuiltinObjectKind::None;
|
||||
}
|
||||
|
||||
BuiltinObjectKind js::BuiltinPrototypeForName(
|
||||
JSContext* cx, const js::frontend::ParserAtom* name) {
|
||||
using WellKnownName = js::frontend::WellKnownParserAtoms;
|
||||
BuiltinObjectKind js::BuiltinPrototypeForName(JSContext* cx, JSAtom* name) {
|
||||
static constexpr BuiltinObjectMap prototypes[] = {
|
||||
{&WellKnownName::Function, BuiltinObjectKind::FunctionPrototype},
|
||||
{&WellKnownName::Object, BuiltinObjectKind::ObjectPrototype},
|
||||
{&WellKnownName::RegExp, BuiltinObjectKind::RegExpPrototype},
|
||||
{&WellKnownName::String, BuiltinObjectKind::StringPrototype},
|
||||
{&JSAtomState::Function, BuiltinObjectKind::FunctionPrototype},
|
||||
{&JSAtomState::Object, BuiltinObjectKind::ObjectPrototype},
|
||||
{&JSAtomState::RegExp, BuiltinObjectKind::RegExpPrototype},
|
||||
{&JSAtomState::String, BuiltinObjectKind::StringPrototype},
|
||||
};
|
||||
|
||||
for (auto& builtin : prototypes) {
|
||||
if (name == cx->parserNames().*(builtin.name)) {
|
||||
if (name == cx->names().*(builtin.name)) {
|
||||
return builtin.kind;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,6 @@ class JS_PUBLIC_API JSObject;
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
class ParserAtom;
|
||||
} // namespace frontend
|
||||
|
||||
class GlobalObject;
|
||||
|
||||
/**
|
||||
|
@ -54,15 +50,13 @@ enum class BuiltinObjectKind : uint8_t {
|
|||
* Return the BuiltinObjectKind for the given constructor name. Return
|
||||
* BuiltinObjectKind::None if no matching constructor was found.
|
||||
*/
|
||||
BuiltinObjectKind BuiltinConstructorForName(JSContext* cx,
|
||||
const frontend::ParserAtom* name);
|
||||
BuiltinObjectKind BuiltinConstructorForName(JSContext* cx, JSAtom* name);
|
||||
|
||||
/**
|
||||
* Return the BuiltinObjectKind for the given prototype name. Return
|
||||
* BuiltinObjectKind::None if no matching prototype was found.
|
||||
*/
|
||||
BuiltinObjectKind BuiltinPrototypeForName(JSContext* cx,
|
||||
const frontend::ParserAtom* name);
|
||||
BuiltinObjectKind BuiltinPrototypeForName(JSContext* cx, JSAtom* name);
|
||||
|
||||
/**
|
||||
* Return the built-in object if already created for the given global. Otherwise
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include "vm/GeneratorObject.h"
|
||||
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
|
@ -385,16 +383,14 @@ bool JSObject::is<js::AbstractGeneratorObject>() const {
|
|||
is<AsyncGeneratorObject>();
|
||||
}
|
||||
|
||||
GeneratorResumeKind js::ParserAtomToResumeKind(
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
const frontend::ParserAtom* atom) {
|
||||
if (atom == compilationInfo.cx->parserNames().next) {
|
||||
GeneratorResumeKind js::AtomToResumeKind(JSContext* cx, JSAtom* atom) {
|
||||
if (atom == cx->names().next) {
|
||||
return GeneratorResumeKind::Next;
|
||||
}
|
||||
if (atom == compilationInfo.cx->parserNames().throw_) {
|
||||
if (atom == cx->names().throw_) {
|
||||
return GeneratorResumeKind::Throw;
|
||||
}
|
||||
MOZ_ASSERT(atom == compilationInfo.cx->parserNames().return_);
|
||||
MOZ_ASSERT(atom == cx->names().return_);
|
||||
return GeneratorResumeKind::Return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
class ParserAtom;
|
||||
struct CompilationInfo;
|
||||
} // namespace frontend
|
||||
|
||||
extern const JSClass GeneratorFunctionClass;
|
||||
|
||||
class AbstractGeneratorObject : public NativeObject {
|
||||
|
@ -225,9 +220,7 @@ inline GeneratorResumeKind ResumeKindFromPC(jsbytecode* pc) {
|
|||
return IntToResumeKind(GET_UINT8(pc));
|
||||
}
|
||||
|
||||
GeneratorResumeKind ParserAtomToResumeKind(
|
||||
frontend::CompilationInfo& compilationInfo,
|
||||
const frontend::ParserAtom* atom);
|
||||
GeneratorResumeKind AtomToResumeKind(JSContext* cx, JSAtom* atom);
|
||||
JSAtom* ResumeKindToAtom(JSContext* cx, GeneratorResumeKind kind);
|
||||
|
||||
} // namespace js
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "jsapi.h"
|
||||
|
||||
#include "debugger/DebugAPI.h"
|
||||
#include "frontend/CompilationInfo.h"
|
||||
#include "proxy/DeadObjectProxy.h"
|
||||
|
||||
#include "vm/JSObject-inl.h"
|
||||
|
@ -93,14 +92,15 @@ static bool StringToInstrumentationKind(JSContext* cx, HandleString str,
|
|||
}
|
||||
|
||||
/* static */
|
||||
const frontend::ParserAtom* RealmInstrumentation::getInstrumentationKindName(
|
||||
frontend::CompilationInfo& compilationInfo, InstrumentationKind kind) {
|
||||
JSAtom* RealmInstrumentation::getInstrumentationKindName(
|
||||
JSContext* cx, InstrumentationKind kind) {
|
||||
for (size_t i = 0; i < mozilla::ArrayLength(instrumentationNames); i++) {
|
||||
if (kind == (InstrumentationKind)(1 << i)) {
|
||||
return compilationInfo.parserAtoms
|
||||
.internAscii(compilationInfo.cx, instrumentationNames[i],
|
||||
strlen(instrumentationNames[i]))
|
||||
.unwrapOr(nullptr);
|
||||
JSString* str = JS_AtomizeString(cx, instrumentationNames[i]);
|
||||
if (!str) {
|
||||
return nullptr;
|
||||
}
|
||||
return &str->asAtom();
|
||||
}
|
||||
}
|
||||
MOZ_CRASH("Unexpected instrumentation kind");
|
||||
|
|
|
@ -12,11 +12,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
struct CompilationInfo;
|
||||
class ParserAtom;
|
||||
} // namespace frontend
|
||||
|
||||
// Logic related to instrumentation which can be performed in a realm.
|
||||
|
||||
#define FOR_EACH_INSTRUMENTATION_KIND(MACRO) \
|
||||
|
@ -69,8 +64,8 @@ class RealmInstrumentation {
|
|||
static uint32_t getInstrumentationKinds(GlobalObject* global);
|
||||
|
||||
// Get the string name of an instrumentation kind.
|
||||
static const frontend::ParserAtom* getInstrumentationKindName(
|
||||
frontend::CompilationInfo& compilationInfo, InstrumentationKind kind);
|
||||
static JSAtom* getInstrumentationKindName(JSContext* cx,
|
||||
InstrumentationKind kind);
|
||||
|
||||
static bool getScriptId(JSContext* cx, Handle<GlobalObject*> global,
|
||||
HandleScript script, int32_t* id);
|
||||
|
|
|
@ -222,7 +222,9 @@ struct JS_PUBLIC_API JSContext : public JS::RootingContext,
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool isInitialized() const { return kind_ != js::ContextKind::Uninitialized; }
|
||||
bool isInitialized() const {
|
||||
return kind_ != js::ContextKind::Uninitialized;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isMainThreadContext() const {
|
||||
|
@ -281,9 +283,13 @@ struct JS_PUBLIC_API JSContext : public JS::RootingContext,
|
|||
|
||||
// Accessors for immutable runtime data.
|
||||
JSAtomState& names() { return *runtime_->commonNames; }
|
||||
#ifdef JS_PARSER_ATOMS
|
||||
js::frontend::WellKnownParserAtoms& parserNames() {
|
||||
return *runtime_->commonParserNames;
|
||||
}
|
||||
#else
|
||||
JSAtomState& parserNames() { return *runtime_->commonNames; }
|
||||
#endif // JS_PARSER_ATOMS
|
||||
js::StaticStrings& staticStrings() { return *runtime_->staticStrings; }
|
||||
js::SharedImmutableStringsCache& sharedImmutableStrings() {
|
||||
return runtime_->sharedImmutableStrings();
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "builtin/ModuleObject.h" // js::{{Im,Ex}portEntry,Requested{Module,}}Object
|
||||
#include "frontend/CompilationInfo.h" // js::frontend::CompilationInfo
|
||||
#include "frontend/EitherParser.h" // js::frontend::EitherParser
|
||||
#include "frontend/ParserAtom.h" // js::frontend::ParserAtom
|
||||
#include "frontend/Stencil.h" // js::frontend::StencilModuleEntry
|
||||
#include "js/GCHashTable.h" // JS::GCHash{Map,Set}
|
||||
#include "js/GCVector.h" // JS::GCVector
|
||||
|
@ -48,7 +47,7 @@ class MOZ_STACK_CLASS ModuleBuilder {
|
|||
bool processExport(frontend::ParseNode* exportNode);
|
||||
bool processExportFrom(frontend::BinaryNode* exportNode);
|
||||
|
||||
bool hasExportedName(const frontend::ParserAtom* name) const;
|
||||
bool hasExportedName(JSAtom* name) const;
|
||||
|
||||
bool buildTables(frontend::StencilModuleMetadata& metadata);
|
||||
|
||||
|
@ -59,10 +58,9 @@ class MOZ_STACK_CLASS ModuleBuilder {
|
|||
|
||||
private:
|
||||
using RequestedModuleVector = JS::GCVector<frontend::StencilModuleEntry>;
|
||||
using AtomSet = JS::GCHashSet<const frontend::ParserAtom*>;
|
||||
using AtomSet = JS::GCHashSet<JSAtom*>;
|
||||
using ExportEntryVector = GCVector<frontend::StencilModuleEntry>;
|
||||
using ImportEntryMap =
|
||||
JS::GCHashMap<const frontend::ParserAtom*, frontend::StencilModuleEntry>;
|
||||
using ImportEntryMap = JS::GCHashMap<JSAtom*, frontend::StencilModuleEntry>;
|
||||
using RootedExportEntryVector = JS::Rooted<ExportEntryVector>;
|
||||
using RootedRequestedModuleVector = JS::Rooted<RequestedModuleVector>;
|
||||
using RootedAtomSet = JS::Rooted<AtomSet>;
|
||||
|
@ -81,23 +79,22 @@ class MOZ_STACK_CLASS ModuleBuilder {
|
|||
// These are populated while emitting bytecode.
|
||||
frontend::FunctionDeclarationVector functionDecls_;
|
||||
|
||||
frontend::StencilModuleEntry* importEntryFor(
|
||||
const frontend::ParserAtom* localName) const;
|
||||
frontend::StencilModuleEntry* importEntryFor(JSAtom* localName) const;
|
||||
|
||||
bool processExportBinding(frontend::ParseNode* pn);
|
||||
bool processExportArrayBinding(frontend::ListNode* array);
|
||||
bool processExportObjectBinding(frontend::ListNode* obj);
|
||||
|
||||
bool appendExportEntry(const frontend::ParserAtom* exportName,
|
||||
const frontend::ParserAtom* localName,
|
||||
bool appendExportEntry(JS::Handle<JSAtom*> exportName,
|
||||
JS::Handle<JSAtom*> localName,
|
||||
frontend::ParseNode* node = nullptr);
|
||||
|
||||
bool appendExportFromEntry(const frontend::ParserAtom* exportName,
|
||||
const frontend::ParserAtom* moduleRequest,
|
||||
const frontend::ParserAtom* importName,
|
||||
bool appendExportFromEntry(JS::Handle<JSAtom*> exportName,
|
||||
JS::Handle<JSAtom*> moduleRequest,
|
||||
JS::Handle<JSAtom*> importName,
|
||||
frontend::ParseNode* node);
|
||||
|
||||
bool maybeAppendRequestedModule(const frontend::ParserAtom* specifier,
|
||||
bool maybeAppendRequestedModule(JS::Handle<JSAtom*> specifier,
|
||||
frontend::ParseNode* node);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "util/Memory.h"
|
||||
#include "util/Text.h"
|
||||
|
@ -379,14 +378,6 @@ bool QuoteString(Sprinter* sp, JSString* str, char quote /*= '\0' */) {
|
|||
sp, linear->twoByteRange(nogc), quote);
|
||||
}
|
||||
|
||||
bool QuoteString(Sprinter* sp, const frontend::ParserAtom* atom,
|
||||
char quote /*= '\0' */) {
|
||||
return atom->hasLatin1Chars()
|
||||
? QuoteString<QuoteTarget::String>(sp, atom->latin1Range(), quote)
|
||||
: QuoteString<QuoteTarget::String>(sp, atom->twoByteRange(),
|
||||
quote);
|
||||
}
|
||||
|
||||
UniqueChars QuoteString(JSContext* cx, JSString* str, char quote /* = '\0' */) {
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init()) {
|
||||
|
@ -398,18 +389,6 @@ UniqueChars QuoteString(JSContext* cx, JSString* str, char quote /* = '\0' */) {
|
|||
return sprinter.release();
|
||||
}
|
||||
|
||||
UniqueChars QuoteString(JSContext* cx, const frontend::ParserAtom* atom,
|
||||
char quote /* = '\0' */) {
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!QuoteString(&sprinter, atom, quote)) {
|
||||
return nullptr;
|
||||
}
|
||||
return sprinter.release();
|
||||
}
|
||||
|
||||
bool JSONQuoteString(Sprinter* sp, JSString* str) {
|
||||
JSLinearString* linear = str->ensureLinear(sp->context);
|
||||
if (!linear) {
|
||||
|
|
|
@ -20,12 +20,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
|
||||
class ParserAtom;
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
class LifoAlloc;
|
||||
|
||||
// Generic printf interface, similar to an ostream in the standard library.
|
||||
|
@ -206,20 +200,10 @@ extern const char js_EscapeMap[];
|
|||
extern JS::UniqueChars QuoteString(JSContext* cx, JSString* str,
|
||||
char quote = '\0');
|
||||
|
||||
// Same as above, except quote a parser atom.
|
||||
extern JS::UniqueChars QuoteString(JSContext* cx,
|
||||
const frontend::ParserAtom* ent,
|
||||
char quote = '\0');
|
||||
|
||||
// Appends the quoted string to the given Sprinter. Follows the same semantics
|
||||
// as QuoteString from above.
|
||||
extern bool QuoteString(Sprinter* sp, JSString* str, char quote = '\0');
|
||||
|
||||
// Appends the quoted parser atom to the given Sprinter. Follows the same
|
||||
// semantics as QuoteString from above.
|
||||
bool QuoteString(Sprinter* sp, const frontend::ParserAtom* ent,
|
||||
char quote = '\0');
|
||||
|
||||
// Appends the JSON quoted string to the given Sprinter.
|
||||
extern bool JSONQuoteString(Sprinter* sp, JSString* str);
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "frontend/SharedContext.h"
|
||||
#include "frontend/Stencil.h"
|
||||
#include "gc/Allocator.h"
|
||||
#include "gc/MaybeRooted.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSScript.h"
|
||||
|
@ -147,60 +146,9 @@ Shape* js::CreateEnvironmentShape(JSContext* cx, BindingIter& bi,
|
|||
return shape;
|
||||
}
|
||||
|
||||
Shape* js::CreateEnvironmentShape(
|
||||
JSContext* cx, AbstractBindingIter<const frontend::ParserAtom>& bi,
|
||||
const JSClass* cls, uint32_t numSlots, uint32_t baseShapeFlags) {
|
||||
RootedShape shape(cx,
|
||||
EmptyEnvironmentShape(cx, cls, numSlots, baseShapeFlags));
|
||||
if (!shape) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedAtom name(cx);
|
||||
StackBaseShape stackBase(cls, baseShapeFlags);
|
||||
for (; bi; bi++) {
|
||||
BindingLocation loc = bi.location();
|
||||
if (loc.kind() == BindingLocation::Kind::Environment) {
|
||||
auto mbJSAtom = bi.name()->toJSAtom(cx);
|
||||
if (mbJSAtom.isErr()) {
|
||||
return nullptr;
|
||||
}
|
||||
name = mbJSAtom.unwrap();
|
||||
MOZ_ASSERT(name);
|
||||
cx->markAtom(name);
|
||||
shape = NextEnvironmentShape(cx, name, bi.kind(), loc.slot(), stackBase,
|
||||
shape);
|
||||
if (!shape) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
template <class Data>
|
||||
inline size_t SizeOfAllocatedData(Data* data) {
|
||||
return SizeOfScopeData<Data>(data->length);
|
||||
}
|
||||
|
||||
template <typename ConcreteScope, typename AtomT>
|
||||
static UniquePtr<AbstractScopeData<ConcreteScope, AtomT>> CopyScopeDataImpl(
|
||||
JSContext* cx, AbstractScopeData<ConcreteScope, AtomT>* data) {
|
||||
using Data = AbstractScopeData<ConcreteScope, AtomT>;
|
||||
|
||||
size_t size = SizeOfAllocatedData(data);
|
||||
void* bytes = cx->pod_malloc<char>(size);
|
||||
if (!bytes) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* dataCopy = new (bytes) Data(*data);
|
||||
|
||||
std::uninitialized_copy_n(data->trailingNames.start(), data->length,
|
||||
dataCopy->trailingNames.start());
|
||||
|
||||
return UniquePtr<Data>(dataCopy);
|
||||
return SizeOfData<Data>(data->length);
|
||||
}
|
||||
|
||||
template <typename ConcreteScope>
|
||||
|
@ -215,13 +163,18 @@ static UniquePtr<typename ConcreteScope::Data> CopyScopeData(
|
|||
cx->markAtom(name);
|
||||
}
|
||||
}
|
||||
return CopyScopeDataImpl<ConcreteScope>(cx, data);
|
||||
}
|
||||
|
||||
template <typename ConcreteScope>
|
||||
static UniquePtr<ParserScopeData<ConcreteScope>> CopyScopeData(
|
||||
JSContext* cx, ParserScopeData<ConcreteScope>* data) {
|
||||
return CopyScopeDataImpl<ConcreteScope>(cx, data);
|
||||
size_t size = SizeOfAllocatedData(data);
|
||||
void* bytes = cx->pod_malloc<char>(size);
|
||||
if (!bytes) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* dataCopy = new (bytes) typename ConcreteScope::Data(*data);
|
||||
|
||||
std::uninitialized_copy_n(names, length, dataCopy->trailingNames.start());
|
||||
|
||||
return UniquePtr<typename ConcreteScope::Data>(dataCopy);
|
||||
}
|
||||
|
||||
static bool SetEnvironmentShape(JSContext* cx, BindingIter& freshBi,
|
||||
|
@ -234,8 +187,8 @@ static bool SetEnvironmentShape(JSContext* cx, BindingIter& freshBi,
|
|||
return envShape;
|
||||
}
|
||||
|
||||
static bool SetEnvironmentShape(JSContext* cx, ParserBindingIter& freshBi,
|
||||
ParserBindingIter& bi, const JSClass* cls,
|
||||
static bool SetEnvironmentShape(JSContext* cx, BindingIter& freshBi,
|
||||
BindingIter& bi, const JSClass* cls,
|
||||
uint32_t firstFrameSlot,
|
||||
uint32_t baseShapeFlags,
|
||||
mozilla::Maybe<uint32_t>* envShape) {
|
||||
|
@ -243,17 +196,16 @@ static bool SetEnvironmentShape(JSContext* cx, ParserBindingIter& freshBi,
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename ConcreteScope, typename AtomT, typename EnvironmentT,
|
||||
typename ShapeT>
|
||||
template <typename ConcreteScope, typename EnvironmentType, typename ShapeType>
|
||||
static bool PrepareScopeData(
|
||||
JSContext* cx, AbstractBindingIter<AtomT>& bi,
|
||||
typename MaybeRootedScopeData<ConcreteScope, AtomT>::HandleType data,
|
||||
uint32_t firstFrameSlot, ShapeT envShape) {
|
||||
const JSClass* cls = &EnvironmentT::class_;
|
||||
uint32_t baseShapeFlags = EnvironmentT::BASESHAPE_FLAGS;
|
||||
JSContext* cx, BindingIter& bi,
|
||||
Handle<UniquePtr<typename ConcreteScope::Data>> data,
|
||||
uint32_t firstFrameSlot, ShapeType envShape) {
|
||||
const JSClass* cls = &EnvironmentType::class_;
|
||||
uint32_t baseShapeFlags = EnvironmentType::BASESHAPE_FLAGS;
|
||||
|
||||
// Copy a fresh BindingIter for use below.
|
||||
AbstractBindingIter<AtomT> freshBi(bi);
|
||||
BindingIter freshBi(bi);
|
||||
|
||||
// Iterate through all bindings. This counts the number of environment
|
||||
// slots needed and computes the maximum frame slot.
|
||||
|
@ -263,9 +215,6 @@ static bool PrepareScopeData(
|
|||
data->nextFrameSlot =
|
||||
bi.canHaveFrameSlots() ? bi.nextFrameSlot() : LOCALNO_LIMIT;
|
||||
|
||||
// Data is not used after this point. Before this point, gc cannot
|
||||
// occur, so `data` is fine as a raw pointer.
|
||||
|
||||
// Make a new environment shape if any environment slots were used.
|
||||
if (bi.nextEnvironmentSlot() != JSSLOT_FREE(cls)) {
|
||||
if (!SetEnvironmentShape(cx, freshBi, bi, cls, firstFrameSlot,
|
||||
|
@ -277,63 +226,16 @@ static bool PrepareScopeData(
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename ConcreteScope, typename AtomT>
|
||||
static UniquePtr<AbstractScopeData<ConcreteScope, AtomT>> NewEmptyScopeData(
|
||||
JSContext* cx, uint32_t length = 0) {
|
||||
using Data = AbstractScopeData<ConcreteScope, AtomT>;
|
||||
|
||||
size_t dataSize = SizeOfScopeData<Data>(length);
|
||||
uint8_t* bytes = cx->pod_malloc<uint8_t>(dataSize);
|
||||
auto data = reinterpret_cast<Data*>(bytes);
|
||||
if (data) {
|
||||
new (data) Data(length);
|
||||
}
|
||||
return UniquePtr<Data>(data);
|
||||
}
|
||||
|
||||
template <typename ConcreteScope>
|
||||
static UniquePtr<typename ConcreteScope::Data> LiftParserScopeData(
|
||||
JSContext* cx, ParserScopeData<ConcreteScope>* data) {
|
||||
using ConcreteData = typename ConcreteScope::Data;
|
||||
|
||||
// Convert all scope ParserAtoms to rooted JSAtoms.
|
||||
// Rooting is necessary as conversion can gc.
|
||||
JS::RootedVector<JSAtom*> jsatoms(cx);
|
||||
if (!jsatoms.reserve(data->length)) {
|
||||
return nullptr;
|
||||
static UniquePtr<typename ConcreteScope::Data> NewEmptyScopeData(
|
||||
JSContext* cx, uint32_t length = 0) {
|
||||
size_t dataSize = SizeOfData<typename ConcreteScope::Data>(length);
|
||||
uint8_t* bytes = cx->pod_malloc<uint8_t>(dataSize);
|
||||
auto data = reinterpret_cast<typename ConcreteScope::Data*>(bytes);
|
||||
if (data) {
|
||||
new (data) typename ConcreteScope::Data(length);
|
||||
}
|
||||
auto* names = data->trailingNames.start();
|
||||
uint32_t length = data->length;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
JSAtom* jsatom = nullptr;
|
||||
if (names[i].name()) {
|
||||
jsatom = names[i].name()->toJSAtom(cx).unwrapOr(nullptr);
|
||||
if (jsatom == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
jsatoms.infallibleAppend(jsatom);
|
||||
}
|
||||
|
||||
// Allocate a new scope-data of the right kind.
|
||||
UniquePtr<ConcreteData> scopeData(
|
||||
NewEmptyScopeData<ConcreteScope, JSAtom>(cx, data->length));
|
||||
if (!scopeData) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Memcopy the head of the structure directly, no translation needed.
|
||||
static_assert(sizeof(ConcreteData) == sizeof(ParserScopeData<ConcreteScope>),
|
||||
"Parser and VM scope-data structures should be same size.");
|
||||
memcpy(scopeData.get(), data, offsetof(ConcreteData, trailingNames));
|
||||
|
||||
// Initialize new scoped names.
|
||||
auto* namesOut = scopeData->trailingNames.start();
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
namesOut[i] = names[i].transformName(jsatoms[i].get());
|
||||
}
|
||||
|
||||
return scopeData;
|
||||
return UniquePtr<typename ConcreteScope::Data>(data);
|
||||
}
|
||||
|
||||
static constexpr size_t HasAtomMask = 1;
|
||||
|
@ -404,7 +306,7 @@ XDRResult Scope::XDRSizedBindingNames(
|
|||
if (mode == XDR_ENCODE) {
|
||||
data.set(&scope->data());
|
||||
} else {
|
||||
data.set(NewEmptyScopeData<ConcreteScope, JSAtom>(cx, length).release());
|
||||
data.set(NewEmptyScopeData<ConcreteScope>(cx, length).release());
|
||||
if (!data) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
@ -468,11 +370,11 @@ inline void Scope::initData(
|
|||
setHeaderPtr(data.get().release());
|
||||
}
|
||||
|
||||
template <typename EnvironmentT>
|
||||
template <typename EnvironmentType>
|
||||
bool Scope::updateEnvShapeIfRequired(JSContext* cx, MutableHandleShape envShape,
|
||||
bool needsEnvironment) {
|
||||
if (!envShape && needsEnvironment) {
|
||||
envShape.set(EmptyEnvironmentShape<EnvironmentT>(cx));
|
||||
envShape.set(EmptyEnvironmentShape<EnvironmentType>(cx));
|
||||
if (!envShape) {
|
||||
return false;
|
||||
}
|
||||
|
@ -480,7 +382,7 @@ bool Scope::updateEnvShapeIfRequired(JSContext* cx, MutableHandleShape envShape,
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename EnvironmentT>
|
||||
template <typename EnvironmentType>
|
||||
bool Scope::updateEnvShapeIfRequired(JSContext* cx,
|
||||
mozilla::Maybe<uint32_t>* envShape,
|
||||
bool needsEnvironment) {
|
||||
|
@ -779,18 +681,18 @@ uint32_t LexicalScope::nextFrameSlot(const AbstractScopePtr& scope) {
|
|||
MOZ_CRASH("Not an enclosing intra-frame Scope");
|
||||
}
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
bool LexicalScope::prepareForScopeCreation(
|
||||
JSContext* cx, ScopeKind kind, uint32_t firstFrameSlot,
|
||||
typename MaybeRootedScopeData<LexicalScope, AtomT>::MutableHandleType data,
|
||||
ShapeT envShape) {
|
||||
template <typename ShapeType>
|
||||
bool LexicalScope::prepareForScopeCreation(JSContext* cx, ScopeKind kind,
|
||||
uint32_t firstFrameSlot,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
ShapeType envShape) {
|
||||
bool isNamedLambda =
|
||||
kind == ScopeKind::NamedLambda || kind == ScopeKind::StrictNamedLambda;
|
||||
|
||||
MOZ_ASSERT_IF(isNamedLambda, firstFrameSlot == LOCALNO_LIMIT);
|
||||
|
||||
AbstractBindingIter<AtomT> bi(*data, firstFrameSlot, isNamedLambda);
|
||||
if (!PrepareScopeData<LexicalScope, AtomT, LexicalEnvironmentObject>(
|
||||
BindingIter bi(*data, firstFrameSlot, isNamedLambda);
|
||||
if (!PrepareScopeData<LexicalScope, LexicalEnvironmentObject>(
|
||||
cx, bi, data, firstFrameSlot, envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -804,8 +706,7 @@ LexicalScope* LexicalScope::createWithData(JSContext* cx, ScopeKind kind,
|
|||
HandleScope enclosing) {
|
||||
RootedShape envShape(cx);
|
||||
|
||||
if (!prepareForScopeCreation<JSAtom>(cx, kind, firstFrameSlot, data,
|
||||
&envShape)) {
|
||||
if (!prepareForScopeCreation(cx, kind, firstFrameSlot, data, &envShape)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -880,16 +781,14 @@ template
|
|||
LexicalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind,
|
||||
HandleScope enclosing, MutableHandleScope scope);
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
template <typename ShapeType>
|
||||
bool FunctionScope::prepareForScopeCreation(
|
||||
JSContext* cx,
|
||||
typename MaybeRootedScopeData<FunctionScope, AtomT>::MutableHandleType data,
|
||||
bool hasParameterExprs, bool needsEnvironment, HandleFunction fun,
|
||||
ShapeT envShape) {
|
||||
JSContext* cx, MutableHandle<UniquePtr<Data>> data, bool hasParameterExprs,
|
||||
bool needsEnvironment, HandleFunction fun, ShapeType envShape) {
|
||||
uint32_t firstFrameSlot = 0;
|
||||
AbstractBindingIter<AtomT> bi(*data, hasParameterExprs);
|
||||
if (!PrepareScopeData<FunctionScope, AtomT, CallObject>(
|
||||
cx, bi, data, firstFrameSlot, envShape)) {
|
||||
BindingIter bi(*data, hasParameterExprs);
|
||||
if (!PrepareScopeData<FunctionScope, CallObject>(cx, bi, data, firstFrameSlot,
|
||||
envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -917,8 +816,8 @@ FunctionScope* FunctionScope::createWithData(
|
|||
// GCPtr. Destruction of |data| below may trigger calls into the GC.
|
||||
RootedShape envShape(cx);
|
||||
|
||||
if (!prepareForScopeCreation<JSAtom>(cx, data, hasParameterExprs,
|
||||
needsEnvironment, fun, &envShape)) {
|
||||
if (!prepareForScopeCreation(cx, data, hasParameterExprs, needsEnvironment,
|
||||
fun, &envShape)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -936,13 +835,6 @@ bool FunctionScope::isSpecialName(JSContext* cx, JSAtom* name) {
|
|||
name == cx->names().dotGenerator;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool FunctionScope::isSpecialName(JSContext* cx, const ParserAtom* name) {
|
||||
return name == cx->parserNames().arguments ||
|
||||
name == cx->parserNames().dotThis ||
|
||||
name == cx->parserNames().dotGenerator;
|
||||
}
|
||||
|
||||
/* static */
|
||||
FunctionScope* FunctionScope::clone(JSContext* cx, Handle<FunctionScope*> scope,
|
||||
HandleFunction fun, HandleScope enclosing) {
|
||||
|
@ -1035,13 +927,24 @@ template
|
|||
FunctionScope::XDR(XDRState<XDR_DECODE>* xdr, HandleFunction fun,
|
||||
HandleScope enclosing, MutableHandleScope scope);
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
bool VarScope::prepareForScopeCreation(
|
||||
JSContext* cx, ScopeKind kind,
|
||||
typename MaybeRootedScopeData<VarScope, AtomT>::MutableHandleType data,
|
||||
uint32_t firstFrameSlot, bool needsEnvironment, ShapeT envShape) {
|
||||
AbstractBindingIter<AtomT> bi(*data, firstFrameSlot);
|
||||
if (!PrepareScopeData<VarScope, AtomT, VarEnvironmentObject>(
|
||||
static UniquePtr<VarScope::Data> NewEmptyVarScopeData(JSContext* cx,
|
||||
uint32_t firstFrameSlot) {
|
||||
UniquePtr<VarScope::Data> data(NewEmptyScopeData<VarScope>(cx));
|
||||
if (data) {
|
||||
data->nextFrameSlot = firstFrameSlot;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template <typename ShapeType>
|
||||
bool VarScope::prepareForScopeCreation(JSContext* cx, ScopeKind kind,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
uint32_t firstFrameSlot,
|
||||
bool needsEnvironment,
|
||||
ShapeType envShape) {
|
||||
BindingIter bi(*data, firstFrameSlot);
|
||||
if (!PrepareScopeData<VarScope, VarEnvironmentObject>(
|
||||
cx, bi, data, firstFrameSlot, envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1063,8 +966,8 @@ VarScope* VarScope::createWithData(JSContext* cx, ScopeKind kind,
|
|||
MOZ_ASSERT(data);
|
||||
|
||||
RootedShape envShape(cx);
|
||||
if (!prepareForScopeCreation<JSAtom>(cx, kind, data, firstFrameSlot,
|
||||
needsEnvironment, &envShape)) {
|
||||
if (!prepareForScopeCreation(cx, kind, data, firstFrameSlot, needsEnvironment,
|
||||
&envShape)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1133,9 +1036,9 @@ GlobalScope* GlobalScope::create(JSContext* cx, ScopeKind kind,
|
|||
Handle<Data*> dataArg) {
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<Data>> data(
|
||||
cx, dataArg ? CopyScopeData<GlobalScope>(cx, dataArg)
|
||||
: NewEmptyScopeData<GlobalScope, JSAtom>(cx));
|
||||
Rooted<UniquePtr<Data>> data(cx, dataArg
|
||||
? CopyScopeData<GlobalScope>(cx, dataArg)
|
||||
: NewEmptyScopeData<GlobalScope>(cx));
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1248,15 +1151,14 @@ template
|
|||
WithScope::XDR(XDRState<XDR_DECODE>* xdr, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
bool EvalScope::prepareForScopeCreation(
|
||||
JSContext* cx, ScopeKind scopeKind,
|
||||
typename MaybeRootedScopeData<EvalScope, AtomT>::MutableHandleType data,
|
||||
ShapeT envShape) {
|
||||
template <typename ShapeType>
|
||||
bool EvalScope::prepareForScopeCreation(JSContext* cx, ScopeKind scopeKind,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
ShapeType envShape) {
|
||||
if (scopeKind == ScopeKind::StrictEval) {
|
||||
uint32_t firstFrameSlot = 0;
|
||||
AbstractBindingIter<AtomT> bi(*data, true);
|
||||
if (!PrepareScopeData<EvalScope, AtomT, VarEnvironmentObject>(
|
||||
BindingIter bi(*data, true);
|
||||
if (!PrepareScopeData<EvalScope, VarEnvironmentObject>(
|
||||
cx, bi, data, firstFrameSlot, envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1277,7 +1179,7 @@ EvalScope* EvalScope::createWithData(JSContext* cx, ScopeKind scopeKind,
|
|||
MOZ_ASSERT(data);
|
||||
|
||||
RootedShape envShape(cx);
|
||||
if (!prepareForScopeCreation<JSAtom>(cx, scopeKind, data, &envShape)) {
|
||||
if (!prepareForScopeCreation(cx, scopeKind, data, &envShape)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1347,14 +1249,14 @@ Zone* ModuleScope::AbstractData<BindingName>::zone() const {
|
|||
}
|
||||
|
||||
/* static */
|
||||
template <typename AtomT, typename ShapeT>
|
||||
bool ModuleScope::prepareForScopeCreation(
|
||||
JSContext* cx,
|
||||
typename MaybeRootedScopeData<ModuleScope, AtomT>::MutableHandleType data,
|
||||
HandleModuleObject module, ShapeT envShape) {
|
||||
template <typename ShapeType>
|
||||
bool ModuleScope::prepareForScopeCreation(JSContext* cx,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
HandleModuleObject module,
|
||||
ShapeType envShape) {
|
||||
uint32_t firstFrameSlot = 0;
|
||||
AbstractBindingIter<AtomT> bi(*data);
|
||||
if (!PrepareScopeData<ModuleScope, AtomT, ModuleEnvironmentObject>(
|
||||
BindingIter bi(*data);
|
||||
if (!PrepareScopeData<ModuleScope, ModuleEnvironmentObject>(
|
||||
cx, bi, data, firstFrameSlot, envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1377,7 +1279,7 @@ ModuleScope* ModuleScope::createWithData(JSContext* cx,
|
|||
MOZ_ASSERT(enclosing->is<GlobalScope>());
|
||||
|
||||
RootedShape envShape(cx);
|
||||
if (!prepareForScopeCreation<JSAtom>(cx, data, module, &envShape)) {
|
||||
if (!prepareForScopeCreation(cx, data, module, &envShape)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1487,7 +1389,7 @@ WasmInstanceScope* WasmInstanceScope::create(JSContext* cx,
|
|||
namesCount += globalsCount;
|
||||
|
||||
Rooted<UniquePtr<Data>> data(
|
||||
cx, NewEmptyScopeData<WasmInstanceScope, JSAtom>(cx, namesCount));
|
||||
cx, NewEmptyScopeData<WasmInstanceScope>(cx, namesCount));
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1543,7 +1445,7 @@ WasmFunctionScope* WasmFunctionScope::create(JSContext* cx,
|
|||
uint32_t namesCount = locals.length();
|
||||
|
||||
Rooted<UniquePtr<Data>> data(
|
||||
cx, NewEmptyScopeData<WasmFunctionScope, JSAtom>(cx, namesCount));
|
||||
cx, NewEmptyScopeData<WasmFunctionScope>(cx, namesCount));
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1570,10 +1472,9 @@ bool ScopeIter::hasSyntacticEnvironment() const {
|
|||
scope()->kind() != ScopeKind::NonSyntactic;
|
||||
}
|
||||
|
||||
AbstractBindingIter<JSAtom>::AbstractBindingIter(ScopeKind kind,
|
||||
BaseScopeData* data,
|
||||
BindingIter::BindingIter(ScopeKind kind, BaseScopeData* data,
|
||||
uint32_t firstFrameSlot)
|
||||
: BaseAbstractBindingIter<JSAtom>() {
|
||||
: Base() {
|
||||
switch (kind) {
|
||||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
|
@ -1623,17 +1524,14 @@ AbstractBindingIter<JSAtom>::AbstractBindingIter(ScopeKind kind,
|
|||
}
|
||||
}
|
||||
|
||||
AbstractBindingIter<JSAtom>::AbstractBindingIter(Scope* scope)
|
||||
: AbstractBindingIter<JSAtom>(scope->kind(), scope->rawData(),
|
||||
scope->firstFrameSlot()) {}
|
||||
BindingIter::BindingIter(Scope* scope)
|
||||
: BindingIter(scope->kind(), scope->rawData(), scope->firstFrameSlot()) {}
|
||||
|
||||
AbstractBindingIter<JSAtom>::AbstractBindingIter(JSScript* script)
|
||||
: AbstractBindingIter<JSAtom>(script->bodyScope()) {}
|
||||
BindingIter::BindingIter(JSScript* script) : BindingIter(script->bodyScope()) {}
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(
|
||||
LexicalScope::AbstractData<NameT>& data, uint32_t firstFrameSlot,
|
||||
uint8_t flags) {
|
||||
void AbstractBindingIter<NameT>::init(LexicalScope::AbstractData<NameT>& data,
|
||||
uint32_t firstFrameSlot, uint8_t flags) {
|
||||
// Named lambda scopes can only have environment slots. If the callee
|
||||
// isn't closed over, it is accessed via JSOp::Callee.
|
||||
if (flags & IsNamedLambda) {
|
||||
|
@ -1656,14 +1554,12 @@ void BaseAbstractBindingIter<NameT>::init(
|
|||
}
|
||||
}
|
||||
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
LexicalScope::AbstractData<JSAtom>&, uint32_t, uint8_t);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
LexicalScope::AbstractData<const ParserAtom>&, uint32_t, uint8_t);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(
|
||||
FunctionScope::AbstractData<NameT>& data, uint8_t flags) {
|
||||
void AbstractBindingIter<NameT>::init(FunctionScope::AbstractData<NameT>& data,
|
||||
uint8_t flags) {
|
||||
flags = CanHaveFrameSlots | CanHaveEnvironmentSlots | flags;
|
||||
if (!(flags & HasFormalParameterExprs)) {
|
||||
flags |= CanHaveArgumentSlots;
|
||||
|
@ -1679,13 +1575,11 @@ void BaseAbstractBindingIter<NameT>::init(
|
|||
data.length, flags, 0, JSSLOT_FREE(&CallObject::class_),
|
||||
data.trailingNames.start(), data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
FunctionScope::AbstractData<JSAtom>&, uint8_t);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
FunctionScope::AbstractData<const ParserAtom>&, uint8_t);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(VarScope::AbstractData<NameT>& data,
|
||||
void AbstractBindingIter<NameT>::init(VarScope::AbstractData<NameT>& data,
|
||||
uint32_t firstFrameSlot) {
|
||||
// imports - [0, 0)
|
||||
// positional formals - [0, 0)
|
||||
|
@ -1698,14 +1592,11 @@ void BaseAbstractBindingIter<NameT>::init(VarScope::AbstractData<NameT>& data,
|
|||
JSSLOT_FREE(&VarEnvironmentObject::class_), data.trailingNames.start(),
|
||||
data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
VarScope::AbstractData<JSAtom>&, uint32_t);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
VarScope::AbstractData<const ParserAtom>&, uint32_t);
|
||||
template void AbstractBindingIter<JSAtom>::init(VarScope::AbstractData<JSAtom>&,
|
||||
uint32_t);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(
|
||||
GlobalScope::AbstractData<NameT>& data) {
|
||||
void AbstractBindingIter<NameT>::init(GlobalScope::AbstractData<NameT>& data) {
|
||||
// imports - [0, 0)
|
||||
// positional formals - [0, 0)
|
||||
// other formals - [0, 0)
|
||||
|
@ -1715,13 +1606,11 @@ void BaseAbstractBindingIter<NameT>::init(
|
|||
init(0, 0, 0, data.letStart, data.constStart, CannotHaveSlots, UINT32_MAX,
|
||||
UINT32_MAX, data.trailingNames.start(), data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
GlobalScope::AbstractData<JSAtom>&);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
GlobalScope::AbstractData<const ParserAtom>&);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(EvalScope::AbstractData<NameT>& data,
|
||||
void AbstractBindingIter<NameT>::init(EvalScope::AbstractData<NameT>& data,
|
||||
bool strict) {
|
||||
uint32_t flags;
|
||||
uint32_t firstFrameSlot;
|
||||
|
@ -1745,14 +1634,11 @@ void BaseAbstractBindingIter<NameT>::init(EvalScope::AbstractData<NameT>& data,
|
|||
init(0, 0, 0, data.length, data.length, flags, firstFrameSlot,
|
||||
firstEnvironmentSlot, data.trailingNames.start(), data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
EvalScope::AbstractData<JSAtom>&, bool);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
EvalScope::AbstractData<const ParserAtom>&, bool);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(
|
||||
ModuleScope::AbstractData<NameT>& data) {
|
||||
void AbstractBindingIter<NameT>::init(ModuleScope::AbstractData<NameT>& data) {
|
||||
// imports - [0, data.varStart)
|
||||
// positional formals - [data.varStart, data.varStart)
|
||||
// other formals - [data.varStart, data.varStart)
|
||||
|
@ -1764,13 +1650,11 @@ void BaseAbstractBindingIter<NameT>::init(
|
|||
JSSLOT_FREE(&ModuleEnvironmentObject::class_),
|
||||
data.trailingNames.start(), data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
ModuleScope::AbstractData<JSAtom>&);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
ModuleScope::AbstractData<const ParserAtom>&);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(
|
||||
void AbstractBindingIter<NameT>::init(
|
||||
WasmInstanceScope::AbstractData<NameT>& data) {
|
||||
// imports - [0, 0)
|
||||
// positional formals - [0, 0)
|
||||
|
@ -1782,13 +1666,11 @@ void BaseAbstractBindingIter<NameT>::init(
|
|||
CanHaveFrameSlots | CanHaveEnvironmentSlots, UINT32_MAX, UINT32_MAX,
|
||||
data.trailingNames.start(), data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
WasmInstanceScope::AbstractData<JSAtom>&);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
WasmInstanceScope::AbstractData<const ParserAtom>&);
|
||||
|
||||
template <typename NameT>
|
||||
void BaseAbstractBindingIter<NameT>::init(
|
||||
void AbstractBindingIter<NameT>::init(
|
||||
WasmFunctionScope::AbstractData<NameT>& data) {
|
||||
// imports - [0, 0)
|
||||
// positional formals - [0, 0)
|
||||
|
@ -1800,10 +1682,8 @@ void BaseAbstractBindingIter<NameT>::init(
|
|||
CanHaveFrameSlots | CanHaveEnvironmentSlots, UINT32_MAX, UINT32_MAX,
|
||||
data.trailingNames.start(), data.length);
|
||||
}
|
||||
template void BaseAbstractBindingIter<JSAtom>::init(
|
||||
template void AbstractBindingIter<JSAtom>::init(
|
||||
WasmFunctionScope::AbstractData<JSAtom>&);
|
||||
template void BaseAbstractBindingIter<const ParserAtom>::init(
|
||||
WasmFunctionScope::AbstractData<const ParserAtom>&);
|
||||
|
||||
PositionalFormalParameterIter::PositionalFormalParameterIter(Scope* scope)
|
||||
: BindingIter(scope) {
|
||||
|
@ -1914,17 +1794,17 @@ JS::ubi::Node::Size JS::ubi::Concrete<Scope>::size(
|
|||
/* static */
|
||||
bool ScopeStencil::createForFunctionScope(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
ParserFunctionScopeData* data, bool hasParameterExprs,
|
||||
Handle<FunctionScope::Data*> dataArg, bool hasParameterExprs,
|
||||
bool needsEnvironment, FunctionIndex functionIndex, bool isArrow,
|
||||
mozilla::Maybe<ScopeIndex> enclosing, ScopeIndex* index) {
|
||||
// If incoming data is null, initialize an epty scope data.
|
||||
if (!data) {
|
||||
data = NewEmptyScopeData<FunctionScope, const frontend::ParserAtom>(cx)
|
||||
.release();
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<FunctionScope::Data>> data(
|
||||
cx, dataArg ? CopyScopeData<FunctionScope>(cx, dataArg)
|
||||
: NewEmptyScopeData<FunctionScope>(cx));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We do not initialize the canonical function while the data is owned by the
|
||||
// ScopeStencil. It gets set in ScopeStencil::releaseData.
|
||||
|
@ -1932,78 +1812,78 @@ bool ScopeStencil::createForFunctionScope(
|
|||
|
||||
uint32_t firstFrameSlot = 0;
|
||||
mozilla::Maybe<uint32_t> envShape;
|
||||
if (!FunctionScope::prepareForScopeCreation<const ParserAtom>(
|
||||
if (!FunctionScope::prepareForScopeCreation(
|
||||
cx, &data, hasParameterExprs, needsEnvironment, fun, &envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*index = compilationInfo.scopeData.length();
|
||||
return compilationInfo.scopeData.emplaceBack(
|
||||
ScopeKind::Function, enclosing, firstFrameSlot, envShape, data,
|
||||
mozilla::Some(functionIndex), isArrow);
|
||||
ScopeKind::Function, enclosing, firstFrameSlot, envShape,
|
||||
std::move(data.get()), mozilla::Some(functionIndex), isArrow);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool ScopeStencil::createForLexicalScope(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo, ScopeKind kind,
|
||||
ParserLexicalScopeData* data, uint32_t firstFrameSlot,
|
||||
Handle<LexicalScope::Data*> dataArg, uint32_t firstFrameSlot,
|
||||
mozilla::Maybe<ScopeIndex> enclosing, ScopeIndex* index) {
|
||||
// If incoming data is null, initialize an epty scope data.
|
||||
if (!data) {
|
||||
data = NewEmptyScopeData<LexicalScope, const frontend::ParserAtom>(cx)
|
||||
.release();
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<LexicalScope::Data>> data(
|
||||
cx, CopyScopeData<LexicalScope>(cx, dataArg));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::Maybe<uint32_t> envShape;
|
||||
if (!LexicalScope::prepareForScopeCreation<const ParserAtom>(
|
||||
cx, kind, firstFrameSlot, &data, &envShape)) {
|
||||
if (!LexicalScope::prepareForScopeCreation(cx, kind, firstFrameSlot, &data,
|
||||
&envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*index = compilationInfo.scopeData.length();
|
||||
return compilationInfo.scopeData.emplaceBack(kind, enclosing, firstFrameSlot,
|
||||
envShape, data);
|
||||
envShape, std::move(data.get()));
|
||||
}
|
||||
|
||||
bool ScopeStencil::createForVarScope(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo, ScopeKind kind,
|
||||
ParserVarScopeData* data, uint32_t firstFrameSlot, bool needsEnvironment,
|
||||
mozilla::Maybe<ScopeIndex> enclosing, ScopeIndex* index) {
|
||||
// If incoming data is null, initialize an epty scope data.
|
||||
if (!data) {
|
||||
data =
|
||||
NewEmptyScopeData<VarScope, const frontend::ParserAtom>(cx).release();
|
||||
Handle<VarScope::Data*> dataArg, uint32_t firstFrameSlot,
|
||||
bool needsEnvironment, mozilla::Maybe<ScopeIndex> enclosing,
|
||||
ScopeIndex* index) {
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<VarScope::Data>> data(
|
||||
cx, dataArg ? CopyScopeData<VarScope>(cx, dataArg)
|
||||
: NewEmptyVarScopeData(cx, firstFrameSlot));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::Maybe<uint32_t> envShape;
|
||||
if (!VarScope::prepareForScopeCreation<const ParserAtom>(
|
||||
cx, kind, &data, firstFrameSlot, needsEnvironment, &envShape)) {
|
||||
if (!VarScope::prepareForScopeCreation(cx, kind, &data, firstFrameSlot,
|
||||
needsEnvironment, &envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*index = compilationInfo.scopeData.length();
|
||||
return compilationInfo.scopeData.emplaceBack(kind, enclosing, firstFrameSlot,
|
||||
envShape, data);
|
||||
envShape, std::move(data.get()));
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool ScopeStencil::createForGlobalScope(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo, ScopeKind kind,
|
||||
ParserGlobalScopeData* data, ScopeIndex* index) {
|
||||
// If incoming data is null, initialize an epty scope data.
|
||||
if (!data) {
|
||||
data = NewEmptyScopeData<GlobalScope, const frontend::ParserAtom>(cx)
|
||||
.release();
|
||||
Handle<GlobalScope::Data*> dataArg, ScopeIndex* index) {
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<GlobalScope::Data>> data(
|
||||
cx, dataArg ? CopyScopeData<GlobalScope>(cx, dataArg)
|
||||
: NewEmptyScopeData<GlobalScope>(cx));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The global scope has no environment shape. Its environment is the
|
||||
// global lexical scope and the global object or non-syntactic objects
|
||||
|
@ -2016,48 +1896,47 @@ bool ScopeStencil::createForGlobalScope(
|
|||
|
||||
*index = compilationInfo.scopeData.length();
|
||||
return compilationInfo.scopeData.emplaceBack(kind, enclosing, firstFrameSlot,
|
||||
envShape, data);
|
||||
envShape, std::move(data.get()));
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool ScopeStencil::createForEvalScope(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo, ScopeKind kind,
|
||||
ParserEvalScopeData* data, mozilla::Maybe<ScopeIndex> enclosing,
|
||||
Handle<EvalScope::Data*> dataArg, mozilla::Maybe<ScopeIndex> enclosing,
|
||||
ScopeIndex* index) {
|
||||
// If incoming data is null, initialize an epty scope data.
|
||||
if (!data) {
|
||||
data =
|
||||
NewEmptyScopeData<EvalScope, const frontend::ParserAtom>(cx).release();
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<EvalScope::Data>> data(
|
||||
cx, dataArg ? CopyScopeData<EvalScope>(cx, dataArg)
|
||||
: NewEmptyScopeData<EvalScope>(cx));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t firstFrameSlot = 0;
|
||||
mozilla::Maybe<uint32_t> envShape;
|
||||
if (!EvalScope::prepareForScopeCreation<const ParserAtom>(cx, kind, &data,
|
||||
&envShape)) {
|
||||
if (!EvalScope::prepareForScopeCreation(cx, kind, &data, &envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*index = compilationInfo.scopeData.length();
|
||||
return compilationInfo.scopeData.emplaceBack(kind, enclosing, firstFrameSlot,
|
||||
envShape, data);
|
||||
envShape, std::move(data.get()));
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool ScopeStencil::createForModuleScope(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
ParserModuleScopeData* data, mozilla::Maybe<ScopeIndex> enclosing,
|
||||
Handle<ModuleScope::Data*> dataArg, mozilla::Maybe<ScopeIndex> enclosing,
|
||||
ScopeIndex* index) {
|
||||
// If incoming data is null, initialize an epty scope data.
|
||||
if (!data) {
|
||||
data = NewEmptyScopeData<ModuleScope, const frontend::ParserAtom>(cx)
|
||||
.release();
|
||||
// The data that's passed in is from the frontend and is LifoAlloc'd.
|
||||
// Copy it now that we're creating a permanent VM scope.
|
||||
Rooted<UniquePtr<ModuleScope::Data>> data(
|
||||
cx, dataArg ? CopyScopeData<ModuleScope>(cx, dataArg)
|
||||
: NewEmptyScopeData<ModuleScope>(cx));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(enclosing.isNothing());
|
||||
|
||||
|
@ -2069,22 +1948,22 @@ bool ScopeStencil::createForModuleScope(
|
|||
// Copy it now that we're creating a permanent VM scope.
|
||||
uint32_t firstFrameSlot = 0;
|
||||
mozilla::Maybe<uint32_t> envShape;
|
||||
if (!ModuleScope::prepareForScopeCreation<const ParserAtom>(cx, &data, module,
|
||||
&envShape)) {
|
||||
if (!ModuleScope::prepareForScopeCreation(cx, &data, module, &envShape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*index = compilationInfo.scopeData.length();
|
||||
return compilationInfo.scopeData.emplaceBack(ScopeKind::Module, enclosing,
|
||||
firstFrameSlot, envShape, data);
|
||||
firstFrameSlot, envShape,
|
||||
std::move(data.get()));
|
||||
}
|
||||
|
||||
template <typename SpecificEnvironmentT>
|
||||
template <typename SpecificEnvironmentType>
|
||||
bool ScopeStencil::createSpecificShape(JSContext* cx, ScopeKind kind,
|
||||
BaseScopeData* scopeData,
|
||||
MutableHandleShape shape) {
|
||||
const JSClass* cls = &SpecificEnvironmentT::class_;
|
||||
uint32_t baseShapeFlags = SpecificEnvironmentT::BASESHAPE_FLAGS;
|
||||
const JSClass* cls = &SpecificEnvironmentType::class_;
|
||||
uint32_t baseShapeFlags = SpecificEnvironmentType::BASESHAPE_FLAGS;
|
||||
|
||||
if (numEnvironmentSlots_.isSome()) {
|
||||
if (*numEnvironmentSlots_ > 0) {
|
||||
|
@ -2113,43 +1992,32 @@ bool ScopeStencil::createForWithScope(
|
|||
firstFrameSlot, envShape);
|
||||
}
|
||||
|
||||
template <typename SpecificScopeT>
|
||||
UniquePtr<typename SpecificScopeT::Data> ScopeStencil::createSpecificScopeData(
|
||||
JSContext* cx, CompilationInfo& compilationInfo) {
|
||||
return LiftParserScopeData<SpecificScopeT>(cx, &data<SpecificScopeT>());
|
||||
template <typename SpecificScopeType>
|
||||
UniquePtr<typename SpecificScopeType::Data> ScopeStencil::releaseData(
|
||||
CompilationInfo& compilationInfo) {
|
||||
return UniquePtr<typename SpecificScopeType::Data>(
|
||||
static_cast<typename SpecificScopeType::Data*>(data_.release()));
|
||||
}
|
||||
|
||||
template <>
|
||||
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>());
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
UniquePtr<FunctionScope::Data> ScopeStencil::releaseData<FunctionScope>(
|
||||
CompilationInfo& compilationInfo) {
|
||||
// Initialize the GCPtrs in the Scope::Data.
|
||||
data<FunctionScope>().canonicalFunction =
|
||||
compilationInfo.functions[*functionIndex_];
|
||||
|
||||
// Initialize the GCPtrs in the FunctionScope::Data.
|
||||
data->canonicalFunction = compilationInfo.functions[*functionIndex_];
|
||||
|
||||
return data;
|
||||
return UniquePtr<FunctionScope::Data>(
|
||||
static_cast<FunctionScope::Data*>(data_.release()));
|
||||
}
|
||||
|
||||
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>());
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
UniquePtr<ModuleScope::Data> ScopeStencil::releaseData<ModuleScope>(
|
||||
CompilationInfo& compilationInfo) {
|
||||
// Initialize the GCPtrs in the Scope::Data.
|
||||
data<ModuleScope>().module = compilationInfo.module;
|
||||
|
||||
// Initialize the GCPtrs in the ModuleScope::Data.
|
||||
data->module = compilationInfo.module;
|
||||
|
||||
return data;
|
||||
return UniquePtr<ModuleScope::Data>(
|
||||
static_cast<ModuleScope::Data*>(data_.release()));
|
||||
}
|
||||
|
||||
// WithScope does not use binding data.
|
||||
|
@ -2165,10 +2033,7 @@ template <>
|
|||
Scope* ScopeStencil::createSpecificScope<GlobalScope, std::nullptr_t>(
|
||||
JSContext* cx, CompilationInfo& compilationInfo) {
|
||||
Rooted<UniquePtr<GlobalScope::Data>> rootedData(
|
||||
cx, createSpecificScopeData<GlobalScope>(cx, compilationInfo));
|
||||
if (!rootedData) {
|
||||
return nullptr;
|
||||
}
|
||||
cx, releaseData<GlobalScope>(compilationInfo));
|
||||
|
||||
MOZ_ASSERT(enclosing(compilationInfo).isNullptr());
|
||||
|
||||
|
@ -2176,17 +2041,14 @@ Scope* ScopeStencil::createSpecificScope<GlobalScope, std::nullptr_t>(
|
|||
return Scope::create<GlobalScope>(cx, kind(), nullptr, nullptr, &rootedData);
|
||||
}
|
||||
|
||||
template <typename SpecificScopeT, typename SpecificEnvironmentT>
|
||||
template <typename SpecificScopeType, typename SpecificEnvironmentType>
|
||||
Scope* ScopeStencil::createSpecificScope(JSContext* cx,
|
||||
CompilationInfo& compilationInfo) {
|
||||
Rooted<UniquePtr<typename SpecificScopeT::Data>> rootedData(
|
||||
cx, createSpecificScopeData<SpecificScopeT>(cx, compilationInfo));
|
||||
if (!rootedData) {
|
||||
return nullptr;
|
||||
}
|
||||
Rooted<UniquePtr<typename SpecificScopeType::Data>> rootedData(
|
||||
cx, releaseData<SpecificScopeType>(compilationInfo));
|
||||
|
||||
RootedShape shape(cx);
|
||||
if (!createSpecificShape<SpecificEnvironmentT>(
|
||||
if (!createSpecificShape<SpecificEnvironmentType>(
|
||||
cx, kind(), rootedData.get().get(), &shape)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2194,7 +2056,7 @@ Scope* ScopeStencil::createSpecificScope(JSContext* cx,
|
|||
RootedScope enclosingScope(cx, enclosing(compilationInfo).existingScope());
|
||||
|
||||
// Because we already baked the data here, we needn't do it again.
|
||||
return Scope::create<SpecificScopeT>(cx, kind(), enclosingScope, shape,
|
||||
return Scope::create<SpecificScopeType>(cx, kind(), enclosingScope, shape,
|
||||
&rootedData);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,23 +26,17 @@
|
|||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
struct CompilationInfo;
|
||||
class ScriptStencil;
|
||||
class ScopeStencil;
|
||||
class ParserAtom;
|
||||
}; // namespace frontend
|
||||
|
||||
template <typename NameT>
|
||||
class AbstractBaseScopeData;
|
||||
|
||||
template <typename NameT>
|
||||
class BaseAbstractBindingIter;
|
||||
|
||||
template <typename NameT>
|
||||
class AbstractBindingIter;
|
||||
|
||||
using BindingIter = AbstractBindingIter<JSAtom>;
|
||||
|
||||
class BindingIter;
|
||||
class ModuleObject;
|
||||
class AbstractScopePtr;
|
||||
|
||||
|
@ -78,9 +72,6 @@ const char* ScopeKindString(ScopeKind kind);
|
|||
|
||||
template <typename NameT>
|
||||
class AbstractBindingName {
|
||||
template <typename OtherNameT>
|
||||
friend class AbstractBindingName;
|
||||
|
||||
// A JSAtom* with its low bit used as a tag for the:
|
||||
// * whether it is closed over (i.e., exists in the environment shape)
|
||||
// * whether it is a top-level function binding in global or eval scope,
|
||||
|
@ -96,10 +87,6 @@ class AbstractBindingName {
|
|||
public:
|
||||
AbstractBindingName() : bits_(0) {}
|
||||
|
||||
template <typename OldNameT>
|
||||
AbstractBindingName(NameT* name, const AbstractBindingName<OldNameT>& old)
|
||||
: bits_(uintptr_t(name) | (old.bits_ & FlagMask)) {}
|
||||
|
||||
AbstractBindingName(NameT* name, bool closedOver,
|
||||
bool isTopLevelFunction = false)
|
||||
: bits_(uintptr_t(name) | (closedOver ? ClosedOverFlag : 0x0) |
|
||||
|
@ -125,13 +112,8 @@ class AbstractBindingName {
|
|||
|
||||
bool closedOver() const { return bits_ & ClosedOverFlag; }
|
||||
|
||||
template <typename NewNameT>
|
||||
AbstractBindingName<NewNameT> transformName(NewNameT* newName) const {
|
||||
return AbstractBindingName<NewNameT>(newName, *this);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class BaseAbstractBindingIter<NameT>;
|
||||
friend class AbstractBindingIter<NameT>;
|
||||
friend class frontend::ScopeStencil;
|
||||
|
||||
// This method should be called only for binding names in `vars` range in
|
||||
|
@ -153,10 +135,7 @@ const size_t ScopeDataAlignBytes = size_t(1) << gc::CellFlagBitsReservedForGC;
|
|||
* suitably aligned to allow storing GC flags in the low bits.
|
||||
*/
|
||||
template <typename NameT>
|
||||
class alignas(ScopeDataAlignBytes) AbstractBaseScopeData {
|
||||
public:
|
||||
using NameType = NameT;
|
||||
};
|
||||
class alignas(ScopeDataAlignBytes) AbstractBaseScopeData {};
|
||||
|
||||
using BaseScopeData = AbstractBaseScopeData<JSAtom>;
|
||||
|
||||
|
@ -175,7 +154,7 @@ using BaseScopeData = AbstractBaseScopeData<JSAtom>;
|
|||
*
|
||||
* The names array is implemented in terms of an generic type that
|
||||
* allows specialization between a (JSAtom*) BindingName and a
|
||||
* ParserAtom
|
||||
* ParserAtomId
|
||||
*/
|
||||
template <typename NameT>
|
||||
class AbstractTrailingNamesArray {
|
||||
|
@ -298,7 +277,7 @@ class WrappedPtrOperations<Scope*, Wrapper> {
|
|||
class Scope : public gc::TenuredCellWithNonGCPointer<BaseScopeData> {
|
||||
friend class GCMarker;
|
||||
friend class frontend::ScopeStencil;
|
||||
friend class js::AbstractBindingIter<JSAtom>;
|
||||
friend class js::BindingIter;
|
||||
|
||||
protected:
|
||||
// The raw data pointer, stored in the cell header.
|
||||
|
@ -337,11 +316,11 @@ class Scope : public gc::TenuredCellWithNonGCPointer<BaseScopeData> {
|
|||
template <typename F>
|
||||
void applyScopeDataTyped(F&& f);
|
||||
|
||||
template <typename EnvironmentT>
|
||||
template <typename EnvironmentType>
|
||||
static bool updateEnvShapeIfRequired(JSContext* cx, MutableHandleShape shape,
|
||||
bool needsEnvironment);
|
||||
|
||||
template <typename EnvironmentT>
|
||||
template <typename EnvironmentType>
|
||||
static bool updateEnvShapeIfRequired(JSContext* cx,
|
||||
mozilla::Maybe<uint32_t>* envShape,
|
||||
bool needsEnvironment);
|
||||
|
@ -433,25 +412,14 @@ class Scope : public gc::TenuredCellWithNonGCPointer<BaseScopeData> {
|
|||
};
|
||||
|
||||
template <class Data>
|
||||
inline size_t SizeOfScopeData(uint32_t numBindings) {
|
||||
return sizeof(Data) + ((numBindings ? numBindings - 1 : 0) *
|
||||
sizeof(AbstractBindingName<typename Data::NameType>));
|
||||
inline size_t SizeOfData(uint32_t numBindings) {
|
||||
static_assert(std::is_base_of_v<BaseScopeData, Data>,
|
||||
"Data must be the correct sort of data, i.e. it must "
|
||||
"inherit from BaseScopeData");
|
||||
return sizeof(Data) +
|
||||
(numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
|
||||
}
|
||||
|
||||
//
|
||||
// A useful typedef for selecting between a gc-aware wrappers
|
||||
// around pointers to BaseScopeData-derived types, and around raw
|
||||
// pointer wrappers around BaseParserScopeData-derived types.
|
||||
//
|
||||
template <typename ScopeT, typename AtomT>
|
||||
using AbstractScopeData = typename ScopeT::template AbstractData<AtomT>;
|
||||
|
||||
template <typename ScopeT, typename AtomT>
|
||||
using MaybeRootedScopeData = std::conditional_t<
|
||||
std::is_same_v<AtomT, JSAtom>,
|
||||
MaybeRooted<UniquePtr<typename ScopeT::Data>, AllowGC::CanGC>,
|
||||
MaybeRooted<AbstractScopeData<ScopeT, AtomT>*, AllowGC::NoGC>>;
|
||||
|
||||
//
|
||||
// A lexical scope that holds let and const bindings. There are 4 kinds of
|
||||
// LexicalScopes.
|
||||
|
@ -475,7 +443,7 @@ using MaybeRootedScopeData = std::conditional_t<
|
|||
//
|
||||
class LexicalScope : public Scope {
|
||||
friend class Scope;
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class GCMarker;
|
||||
friend class frontend::ScopeStencil;
|
||||
|
||||
|
@ -516,12 +484,11 @@ class LexicalScope : public Scope {
|
|||
uint32_t firstFrameSlot,
|
||||
HandleScope enclosing);
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
static bool prepareForScopeCreation(
|
||||
JSContext* cx, ScopeKind kind, uint32_t firstFrameSlot,
|
||||
typename MaybeRootedScopeData<LexicalScope, AtomT>::MutableHandleType
|
||||
data,
|
||||
ShapeT envShape);
|
||||
template <typename ShapeType>
|
||||
static bool prepareForScopeCreation(JSContext* cx, ScopeKind kind,
|
||||
uint32_t firstFrameSlot,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
ShapeType envShape);
|
||||
|
||||
Data& data() { return *static_cast<Data*>(rawData()); }
|
||||
const Data& data() const { return *static_cast<const Data*>(rawData()); }
|
||||
|
@ -564,7 +531,7 @@ inline bool Scope::is<LexicalScope>() const {
|
|||
//
|
||||
class FunctionScope : public Scope {
|
||||
friend class GCMarker;
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class PositionalFormalParameterIter;
|
||||
friend class Scope;
|
||||
friend class AbstractScopePtr;
|
||||
|
@ -630,13 +597,12 @@ class FunctionScope : public Scope {
|
|||
|
||||
using Data = AbstractData<JSAtom>;
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
static bool prepareForScopeCreation(
|
||||
JSContext* cx,
|
||||
typename MaybeRootedScopeData<FunctionScope, AtomT>::MutableHandleType
|
||||
data,
|
||||
bool hasParameterExprs, bool needsEnvironment, HandleFunction fun,
|
||||
ShapeT envShape);
|
||||
template <typename ShapeType>
|
||||
static bool prepareForScopeCreation(JSContext* cx,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
bool hasParameterExprs,
|
||||
bool needsEnvironment, HandleFunction fun,
|
||||
ShapeType envShape);
|
||||
|
||||
static FunctionScope* clone(JSContext* cx, Handle<FunctionScope*> scope,
|
||||
HandleFunction fun, HandleScope enclosing);
|
||||
|
@ -671,7 +637,6 @@ class FunctionScope : public Scope {
|
|||
}
|
||||
|
||||
static bool isSpecialName(JSContext* cx, JSAtom* name);
|
||||
static bool isSpecialName(JSContext* cx, const frontend::ParserAtom* name);
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -685,7 +650,7 @@ class FunctionScope : public Scope {
|
|||
//
|
||||
class VarScope : public Scope {
|
||||
friend class GCMarker;
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class Scope;
|
||||
friend class frontend::ScopeStencil;
|
||||
|
||||
|
@ -723,11 +688,12 @@ class VarScope : public Scope {
|
|||
uint32_t firstFrameSlot,
|
||||
bool needsEnvironment, HandleScope enclosing);
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
static bool prepareForScopeCreation(
|
||||
JSContext* cx, ScopeKind kind,
|
||||
typename MaybeRootedScopeData<VarScope, AtomT>::MutableHandleType data,
|
||||
uint32_t firstFrameSlot, bool needsEnvironment, ShapeT envShape);
|
||||
template <typename ShapeType>
|
||||
static bool prepareForScopeCreation(JSContext* cx, ScopeKind kind,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
uint32_t firstFrameSlot,
|
||||
bool needsEnvironment,
|
||||
ShapeType envShape);
|
||||
|
||||
Data& data() { return *static_cast<Data*>(rawData()); }
|
||||
|
||||
|
@ -763,14 +729,14 @@ inline bool Scope::is<VarScope>() const {
|
|||
//
|
||||
class GlobalScope : public Scope {
|
||||
friend class Scope;
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class GCMarker;
|
||||
|
||||
public:
|
||||
// Data is public because it is created by the frontend. See
|
||||
// Parser<FullParseHandler>::newGlobalScopeData.
|
||||
template <typename NameT>
|
||||
struct AbstractData : public AbstractBaseScopeData<NameT> {
|
||||
struct AbstractData : BaseScopeData {
|
||||
// Bindings are sorted by kind.
|
||||
// `vars` includes top-level functions which is distinguished by a bit
|
||||
// on the BindingName.
|
||||
|
@ -855,7 +821,7 @@ class WithScope : public Scope {
|
|||
//
|
||||
class EvalScope : public Scope {
|
||||
friend class Scope;
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class GCMarker;
|
||||
friend class frontend::ScopeStencil;
|
||||
|
||||
|
@ -896,11 +862,10 @@ class EvalScope : public Scope {
|
|||
MutableHandle<UniquePtr<Data>> data,
|
||||
HandleScope enclosing);
|
||||
|
||||
template <typename AtomT, typename ShapeT>
|
||||
static bool prepareForScopeCreation(
|
||||
JSContext* cx, ScopeKind scopeKind,
|
||||
typename MaybeRootedScopeData<EvalScope, AtomT>::MutableHandleType data,
|
||||
ShapeT envShape);
|
||||
template <typename ShapeType>
|
||||
static bool prepareForScopeCreation(JSContext* cx, ScopeKind scopeKind,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
ShapeType envShape);
|
||||
|
||||
Data& data() { return *static_cast<Data*>(rawData()); }
|
||||
|
||||
|
@ -940,7 +905,7 @@ inline bool Scope::is<EvalScope>() const {
|
|||
//
|
||||
class ModuleScope : public Scope {
|
||||
friend class GCMarker;
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class Scope;
|
||||
friend class AbstractScopePtr;
|
||||
friend class frontend::ScopeStencil;
|
||||
|
@ -950,7 +915,7 @@ class ModuleScope : public Scope {
|
|||
// Data is public because it is created by the frontend. See
|
||||
// Parser<FullParseHandler>::newModuleScopeData.
|
||||
template <typename NameT>
|
||||
struct AbstractData : public AbstractBaseScopeData<NameT> {
|
||||
struct AbstractData : BaseScopeData {
|
||||
// The module of the scope.
|
||||
GCPtr<ModuleObject*> module = {};
|
||||
|
||||
|
@ -989,11 +954,11 @@ class ModuleScope : public Scope {
|
|||
MutableHandle<UniquePtr<Data>> data,
|
||||
Handle<ModuleObject*> module,
|
||||
HandleScope enclosing);
|
||||
template <typename AtomT, typename ShapeT>
|
||||
static bool prepareForScopeCreation(
|
||||
JSContext* cx,
|
||||
typename MaybeRootedScopeData<ModuleScope, AtomT>::MutableHandleType data,
|
||||
HandleModuleObject module, ShapeT envShape);
|
||||
template <typename ShapeType>
|
||||
static bool prepareForScopeCreation(JSContext* cx,
|
||||
MutableHandle<UniquePtr<Data>> data,
|
||||
HandleModuleObject module,
|
||||
ShapeType envShape);
|
||||
|
||||
Data& data() { return *static_cast<Data*>(rawData()); }
|
||||
|
||||
|
@ -1006,7 +971,7 @@ class ModuleScope : public Scope {
|
|||
};
|
||||
|
||||
class WasmInstanceScope : public Scope {
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class Scope;
|
||||
friend class GCMarker;
|
||||
friend class AbstractScopePtr;
|
||||
|
@ -1060,7 +1025,7 @@ class WasmInstanceScope : public Scope {
|
|||
// Debugger only, and not for wasm execution.
|
||||
//
|
||||
class WasmFunctionScope : public Scope {
|
||||
friend class AbstractBindingIter<JSAtom>;
|
||||
friend class BindingIter;
|
||||
friend class Scope;
|
||||
friend class GCMarker;
|
||||
friend class AbstractScopePtr;
|
||||
|
@ -1152,7 +1117,7 @@ void Scope::applyScopeDataTyped(F&& f) {
|
|||
// }
|
||||
//
|
||||
template <typename NameT>
|
||||
class BaseAbstractBindingIter {
|
||||
class AbstractBindingIter {
|
||||
protected:
|
||||
// Bindings are sorted by kind. Because different Scopes have differently
|
||||
// laid out Data for packing, BindingIter must handle all binding kinds.
|
||||
|
@ -1294,44 +1259,43 @@ class BaseAbstractBindingIter {
|
|||
}
|
||||
}
|
||||
|
||||
BaseAbstractBindingIter() = default;
|
||||
AbstractBindingIter() = default;
|
||||
|
||||
public:
|
||||
BaseAbstractBindingIter(LexicalScope::AbstractData<NameT>& data,
|
||||
AbstractBindingIter(LexicalScope::AbstractData<NameT>& data,
|
||||
uint32_t firstFrameSlot, bool isNamedLambda) {
|
||||
init(data, firstFrameSlot, isNamedLambda ? IsNamedLambda : 0);
|
||||
}
|
||||
|
||||
BaseAbstractBindingIter(FunctionScope::AbstractData<NameT>& data,
|
||||
AbstractBindingIter(FunctionScope::AbstractData<NameT>& data,
|
||||
bool hasParameterExprs) {
|
||||
init(data, IgnoreDestructuredFormalParameters |
|
||||
(hasParameterExprs ? HasFormalParameterExprs : 0));
|
||||
}
|
||||
|
||||
BaseAbstractBindingIter(VarScope::AbstractData<NameT>& data,
|
||||
AbstractBindingIter(VarScope::AbstractData<NameT>& data,
|
||||
uint32_t firstFrameSlot) {
|
||||
init(data, firstFrameSlot);
|
||||
}
|
||||
|
||||
explicit BaseAbstractBindingIter(GlobalScope::AbstractData<NameT>& data) {
|
||||
explicit AbstractBindingIter(GlobalScope::AbstractData<NameT>& data) {
|
||||
init(data);
|
||||
}
|
||||
|
||||
explicit BaseAbstractBindingIter(ModuleScope::AbstractData<NameT>& data) {
|
||||
explicit AbstractBindingIter(ModuleScope::AbstractData<NameT>& data) {
|
||||
init(data);
|
||||
}
|
||||
|
||||
explicit BaseAbstractBindingIter(
|
||||
WasmFunctionScope::AbstractData<NameT>& data) {
|
||||
explicit AbstractBindingIter(WasmFunctionScope::AbstractData<NameT>& data) {
|
||||
init(data);
|
||||
}
|
||||
|
||||
BaseAbstractBindingIter(EvalScope::AbstractData<NameT>& data, bool strict) {
|
||||
AbstractBindingIter(EvalScope::AbstractData<NameT>& data, bool strict) {
|
||||
init(data, strict);
|
||||
}
|
||||
|
||||
MOZ_IMPLICIT BaseAbstractBindingIter(
|
||||
const BaseAbstractBindingIter<NameT>& bi) = default;
|
||||
MOZ_IMPLICIT AbstractBindingIter(const AbstractBindingIter<NameT>& bi) =
|
||||
default;
|
||||
|
||||
bool done() const { return index_ == length_; }
|
||||
|
||||
|
@ -1444,34 +1408,22 @@ class BaseAbstractBindingIter {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename NameT>
|
||||
class AbstractBindingIter;
|
||||
|
||||
template <>
|
||||
class AbstractBindingIter<JSAtom> : public BaseAbstractBindingIter<JSAtom> {
|
||||
using Base = BaseAbstractBindingIter<JSAtom>;
|
||||
class BindingIter : public AbstractBindingIter<JSAtom> {
|
||||
using Base = AbstractBindingIter<JSAtom>;
|
||||
|
||||
public:
|
||||
AbstractBindingIter<JSAtom>(ScopeKind kind, BaseScopeData* data,
|
||||
uint32_t firstFrameSlot);
|
||||
BindingIter(ScopeKind kind, BaseScopeData* data, uint32_t firstFrameSlot);
|
||||
|
||||
explicit AbstractBindingIter<JSAtom>(Scope* scope);
|
||||
explicit AbstractBindingIter<JSAtom>(JSScript* script);
|
||||
explicit BindingIter(Scope* scope);
|
||||
explicit BindingIter(JSScript* script);
|
||||
|
||||
using Base::Base;
|
||||
|
||||
MOZ_IMPLICIT BindingIter(const BindingIter& bi) = default;
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
template <>
|
||||
class AbstractBindingIter<const frontend::ParserAtom>
|
||||
: public BaseAbstractBindingIter<const frontend::ParserAtom> {
|
||||
using Base = BaseAbstractBindingIter<const frontend::ParserAtom>;
|
||||
|
||||
public:
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
void DumpBindings(JSContext* cx, Scope* scope);
|
||||
JSAtom* FrameSlotName(JSScript* script, jsbytecode* pc);
|
||||
|
||||
|
@ -1632,10 +1584,6 @@ Shape* CreateEnvironmentShape(JSContext* cx, BindingIter& bi,
|
|||
const JSClass* cls, uint32_t numSlots,
|
||||
uint32_t baseShapeFlags);
|
||||
|
||||
Shape* CreateEnvironmentShape(
|
||||
JSContext* cx, 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);
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "builtin/String.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
#include "frontend/ParserAtom.h" // js::frontend::ParserAtom
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Policy.h"
|
||||
#include "jit/AtomicOperations.h"
|
||||
|
@ -958,16 +957,6 @@ bool js::IsExtendedUnclonedSelfHostedFunctionName(JSAtom* name) {
|
|||
}
|
||||
return name->latin1OrTwoByteChar(0) == '$';
|
||||
}
|
||||
bool js::IsExtendedUnclonedSelfHostedFunctionName(
|
||||
const frontend::ParserAtom* id) {
|
||||
if (id->length() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char16_t ch =
|
||||
id->hasLatin1Chars() ? id->latin1Chars()[0] : id->twoByteChars()[0];
|
||||
return ch == '$';
|
||||
}
|
||||
|
||||
static void SetUnclonedSelfHostedFunctionName(JSFunction* fun, JSAtom* name) {
|
||||
fun->setExtendedSlot(ORIGINAL_FUNCTION_NAME_SLOT, StringValue(name));
|
||||
|
|
|
@ -14,10 +14,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
class ParserAtom;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the given JSFunction is a self-hosted function whose
|
||||
* self-hosted name is the given name.
|
||||
|
@ -49,7 +45,6 @@ PropertyName* GetClonedSelfHostedFunctionNameOffMainThread(JSFunction* fun);
|
|||
* extended function, to store the original name in `_SetCanonicalName`.
|
||||
*/
|
||||
bool IsExtendedUnclonedSelfHostedFunctionName(JSAtom* name);
|
||||
bool IsExtendedUnclonedSelfHostedFunctionName(const frontend::ParserAtom* id);
|
||||
|
||||
bool IsCallSelfHostedNonGenericMethod(NativeImpl impl);
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "jsfriendapi.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/ParserAtom.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/MaybeRooted.h"
|
||||
#include "gc/Nursery.h"
|
||||
|
@ -1506,14 +1505,6 @@ bool AutoStableStringChars::copyTwoByteChars(JSContext* cx,
|
|||
return true;
|
||||
}
|
||||
|
||||
UniqueChars js::ParserAtomToNewUTF8CharsZ(
|
||||
JSContext* maybecx, const js::frontend::ParserAtom* atom) {
|
||||
return UniqueChars(
|
||||
atom->hasLatin1Chars()
|
||||
? JS::CharsToNewUTF8CharsZ(maybecx, atom->latin1Range()).c_str()
|
||||
: JS::CharsToNewUTF8CharsZ(maybecx, atom->twoByteRange()).c_str());
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(JS_JITSPEW)
|
||||
void JSAtom::dump(js::GenericPrinter& out) {
|
||||
out.printf("JSAtom* (%p) = ", (void*)this);
|
||||
|
|
|
@ -45,12 +45,6 @@ class JS_FRIEND_API AutoStableStringChars;
|
|||
|
||||
namespace js {
|
||||
|
||||
namespace frontend {
|
||||
|
||||
class ParserAtom;
|
||||
|
||||
} // namespace frontend
|
||||
|
||||
class StaticStrings;
|
||||
class PropertyName;
|
||||
|
||||
|
@ -1476,9 +1470,6 @@ static inline UniqueChars StringToNewUTF8CharsZ(JSContext* maybecx,
|
|||
.c_str());
|
||||
}
|
||||
|
||||
UniqueChars ParserAtomToNewUTF8CharsZ(JSContext* maybecx,
|
||||
const js::frontend::ParserAtom* atom);
|
||||
|
||||
/**
|
||||
* Allocate a string with the given contents. If |allowGC == CanGC|, this may
|
||||
* trigger a GC.
|
||||
|
|
|
@ -539,13 +539,13 @@ static inline ParseNode* ExpressionStatementExpr(ParseNode* pn) {
|
|||
return UnaryKid(pn);
|
||||
}
|
||||
|
||||
static inline const ParserName* LoopControlMaybeLabel(ParseNode* pn) {
|
||||
static inline PropertyName* LoopControlMaybeLabel(ParseNode* pn) {
|
||||
MOZ_ASSERT(pn->isKind(ParseNodeKind::BreakStmt) ||
|
||||
pn->isKind(ParseNodeKind::ContinueStmt));
|
||||
return pn->as<LoopControlStatement>().label();
|
||||
}
|
||||
|
||||
static inline const ParserName* LabeledStatementLabel(ParseNode* pn) {
|
||||
static inline PropertyName* LabeledStatementLabel(ParseNode* pn) {
|
||||
return pn->as<LabeledStatement>().label();
|
||||
}
|
||||
|
||||
|
@ -565,8 +565,8 @@ static ParseNode* DotBase(ParseNode* pn) {
|
|||
return &pn->as<PropertyAccess>().expression();
|
||||
}
|
||||
|
||||
static const ParserName* DotMember(ParseNode* pn) {
|
||||
return pn->as<PropertyAccess>().name();
|
||||
static PropertyName* DotMember(ParseNode* pn) {
|
||||
return &pn->as<PropertyAccess>().name();
|
||||
}
|
||||
|
||||
static ParseNode* ElemBase(ParseNode* pn) {
|
||||
|
@ -577,9 +577,9 @@ static ParseNode* ElemIndex(ParseNode* pn) {
|
|||
return &pn->as<PropertyByValue>().key();
|
||||
}
|
||||
|
||||
static inline const ParserName* FunctionName(FunctionNode* funNode) {
|
||||
if (const ParserAtom* name = funNode->funbox()->explicitName()) {
|
||||
return name->asName();
|
||||
static inline PropertyName* FunctionName(FunctionNode* funNode) {
|
||||
if (JSAtom* name = funNode->funbox()->explicitName()) {
|
||||
return name->asPropertyName();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -600,10 +600,10 @@ static inline bool IsNormalObjectField(ParseNode* pn) {
|
|||
BinaryLeft(pn)->isKind(ParseNodeKind::ObjectPropertyName);
|
||||
}
|
||||
|
||||
static inline const ParserName* ObjectNormalFieldName(ParseNode* pn) {
|
||||
static inline PropertyName* ObjectNormalFieldName(ParseNode* pn) {
|
||||
MOZ_ASSERT(IsNormalObjectField(pn));
|
||||
MOZ_ASSERT(BinaryLeft(pn)->isKind(ParseNodeKind::ObjectPropertyName));
|
||||
return BinaryLeft(pn)->as<NameNode>().atom()->asName();
|
||||
return BinaryLeft(pn)->as<NameNode>().atom()->asPropertyName();
|
||||
}
|
||||
|
||||
static inline ParseNode* ObjectNormalFieldInitializer(ParseNode* pn) {
|
||||
|
@ -611,12 +611,11 @@ static inline ParseNode* ObjectNormalFieldInitializer(ParseNode* pn) {
|
|||
return BinaryRight(pn);
|
||||
}
|
||||
|
||||
static inline bool IsUseOfName(ParseNode* pn, const ParserName* name) {
|
||||
static inline bool IsUseOfName(ParseNode* pn, PropertyName* name) {
|
||||
return pn->isName(name);
|
||||
}
|
||||
|
||||
static inline bool IsIgnoredDirectiveName(JSContext* cx,
|
||||
const ParserAtom* atom) {
|
||||
static inline bool IsIgnoredDirectiveName(JSContext* cx, JSAtom* atom) {
|
||||
return atom != cx->parserNames().useStrict;
|
||||
}
|
||||
|
||||
|
@ -1038,7 +1037,7 @@ static const unsigned VALIDATION_LIFO_DEFAULT_CHUNK_SIZE = 4 * 1024;
|
|||
class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
||||
public:
|
||||
class Func {
|
||||
const ParserName* name_;
|
||||
PropertyName* name_;
|
||||
uint32_t sigIndex_;
|
||||
uint32_t firstUse_;
|
||||
uint32_t funcDefIndex_;
|
||||
|
@ -1053,7 +1052,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
Uint32Vector callSiteLineNums_;
|
||||
|
||||
public:
|
||||
Func(const ParserName* name, uint32_t sigIndex, uint32_t firstUse,
|
||||
Func(PropertyName* name, uint32_t sigIndex, uint32_t firstUse,
|
||||
uint32_t funcDefIndex)
|
||||
: name_(name),
|
||||
sigIndex_(sigIndex),
|
||||
|
@ -1064,7 +1063,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
srcEnd_(0),
|
||||
line_(0) {}
|
||||
|
||||
const ParserName* name() const { return name_; }
|
||||
PropertyName* name() const { return name_; }
|
||||
uint32_t sigIndex() const { return sigIndex_; }
|
||||
uint32_t firstUse() const { return firstUse_; }
|
||||
bool defined() const { return defined_; }
|
||||
|
@ -1108,7 +1107,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
|
||||
class Table {
|
||||
uint32_t sigIndex_;
|
||||
const ParserName* name_;
|
||||
PropertyName* name_;
|
||||
uint32_t firstUse_;
|
||||
uint32_t mask_;
|
||||
bool defined_;
|
||||
|
@ -1116,7 +1115,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
Table(Table&& rhs) = delete;
|
||||
|
||||
public:
|
||||
Table(uint32_t sigIndex, const ParserName* name, uint32_t firstUse,
|
||||
Table(uint32_t sigIndex, PropertyName* name, uint32_t firstUse,
|
||||
uint32_t mask)
|
||||
: sigIndex_(sigIndex),
|
||||
name_(name),
|
||||
|
@ -1125,7 +1124,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
defined_(false) {}
|
||||
|
||||
uint32_t sigIndex() const { return sigIndex_; }
|
||||
const ParserName* name() const { return name_; }
|
||||
PropertyName* name() const { return name_; }
|
||||
uint32_t firstUse() const { return firstUse_; }
|
||||
unsigned mask() const { return mask_; }
|
||||
bool defined() const { return defined_; }
|
||||
|
@ -1257,10 +1256,9 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
};
|
||||
|
||||
struct ArrayView {
|
||||
ArrayView(const ParserName* name, Scalar::Type type)
|
||||
: name(name), type(type) {}
|
||||
ArrayView(PropertyName* name, Scalar::Type type) : name(name), type(type) {}
|
||||
|
||||
const ParserName* name;
|
||||
PropertyName* name;
|
||||
Scalar::Type type;
|
||||
};
|
||||
|
||||
|
@ -1284,19 +1282,18 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
};
|
||||
|
||||
class NamedSig : public HashableSig {
|
||||
const ParserName* name_;
|
||||
PropertyName* name_;
|
||||
|
||||
public:
|
||||
NamedSig(const ParserName* name, uint32_t sigIndex,
|
||||
const TypeDefVector& types)
|
||||
NamedSig(PropertyName* name, uint32_t sigIndex, const TypeDefVector& types)
|
||||
: HashableSig(sigIndex, types), name_(name) {}
|
||||
const ParserName* name() const { return name_; }
|
||||
PropertyName* name() const { return name_; }
|
||||
|
||||
// Implement HashPolicy:
|
||||
struct Lookup {
|
||||
const ParserName* name;
|
||||
PropertyName* name;
|
||||
const FuncType& funcType;
|
||||
Lookup(const ParserName* name, const FuncType& funcType)
|
||||
Lookup(PropertyName* name, const FuncType& funcType)
|
||||
: name(name), funcType(funcType) {}
|
||||
};
|
||||
static HashNumber hash(Lookup l) {
|
||||
|
@ -1309,18 +1306,17 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
|
||||
using SigSet = HashSet<HashableSig, HashableSig>;
|
||||
using FuncImportMap = HashMap<NamedSig, uint32_t, NamedSig>;
|
||||
using GlobalMap = HashMap<const ParserName*, Global*>;
|
||||
using MathNameMap = HashMap<const ParserName*, MathBuiltin>;
|
||||
using GlobalMap = HashMap<PropertyName*, Global*>;
|
||||
using MathNameMap = HashMap<PropertyName*, MathBuiltin>;
|
||||
using ArrayViewVector = Vector<ArrayView>;
|
||||
|
||||
protected:
|
||||
JSContext* cx_;
|
||||
CompilationInfo& compilationInfo_;
|
||||
FunctionNode* moduleFunctionNode_;
|
||||
const ParserName* moduleFunctionName_;
|
||||
const ParserName* globalArgumentName_ = nullptr;
|
||||
const ParserName* importArgumentName_ = nullptr;
|
||||
const ParserName* bufferArgumentName_ = nullptr;
|
||||
PropertyName* moduleFunctionName_;
|
||||
PropertyName* globalArgumentName_ = nullptr;
|
||||
PropertyName* importArgumentName_ = nullptr;
|
||||
PropertyName* bufferArgumentName_ = nullptr;
|
||||
MathNameMap standardLibraryMathNames_;
|
||||
|
||||
// Validation-internal state:
|
||||
|
@ -1343,10 +1339,8 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
bool errorOverRecursed_ = false;
|
||||
|
||||
protected:
|
||||
ModuleValidatorShared(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
FunctionNode* moduleFunctionNode)
|
||||
ModuleValidatorShared(JSContext* cx, FunctionNode* moduleFunctionNode)
|
||||
: cx_(cx),
|
||||
compilationInfo_(compilationInfo),
|
||||
moduleFunctionNode_(moduleFunctionNode),
|
||||
moduleFunctionName_(FunctionName(moduleFunctionNode)),
|
||||
standardLibraryMathNames_(cx),
|
||||
|
@ -1386,13 +1380,12 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
|
||||
auto AddMathFunction = [this](const char* name,
|
||||
AsmJSMathBuiltinFunction func) {
|
||||
auto mbAtom =
|
||||
compilationInfo_.parserAtoms.internAscii(cx_, name, strlen(name));
|
||||
if (mbAtom.isErr()) {
|
||||
JSAtom* atom = Atomize(cx_, name, strlen(name));
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
MathBuiltin builtin(func);
|
||||
return this->standardLibraryMathNames_.putNew(mbAtom.unwrap()->asName(),
|
||||
return this->standardLibraryMathNames_.putNew(atom->asPropertyName(),
|
||||
builtin);
|
||||
};
|
||||
|
||||
|
@ -1417,13 +1410,12 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
};
|
||||
|
||||
auto AddMathConstant = [this](const char* name, double cst) {
|
||||
auto mbAtom =
|
||||
compilationInfo_.parserAtoms.internAscii(cx_, name, strlen(name));
|
||||
if (mbAtom.isErr()) {
|
||||
JSAtom* atom = Atomize(cx_, name, strlen(name));
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
MathBuiltin builtin(cst);
|
||||
return this->standardLibraryMathNames_.putNew(mbAtom.unwrap()->asName(),
|
||||
return this->standardLibraryMathNames_.putNew(atom->asPropertyName(),
|
||||
builtin);
|
||||
};
|
||||
|
||||
|
@ -1438,49 +1430,52 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
|
||||
public:
|
||||
JSContext* cx() const { return cx_; }
|
||||
const ParserName* moduleFunctionName() const { return moduleFunctionName_; }
|
||||
const ParserName* globalArgumentName() const { return globalArgumentName_; }
|
||||
const ParserName* importArgumentName() const { return importArgumentName_; }
|
||||
const ParserName* bufferArgumentName() const { return bufferArgumentName_; }
|
||||
PropertyName* moduleFunctionName() const { return moduleFunctionName_; }
|
||||
PropertyName* globalArgumentName() const { return globalArgumentName_; }
|
||||
PropertyName* importArgumentName() const { return importArgumentName_; }
|
||||
PropertyName* bufferArgumentName() const { return bufferArgumentName_; }
|
||||
const ModuleEnvironment& env() { return env_; }
|
||||
|
||||
uint64_t minMemoryLength() const { return env_.minMemoryLength; }
|
||||
|
||||
void initModuleFunctionName(const ParserName* name) {
|
||||
void initModuleFunctionName(PropertyName* name) {
|
||||
MOZ_ASSERT(!moduleFunctionName_);
|
||||
moduleFunctionName_ = name;
|
||||
}
|
||||
MOZ_MUST_USE bool initGlobalArgumentName(const ParserName* n) {
|
||||
MOZ_MUST_USE bool initGlobalArgumentName(PropertyName* n) {
|
||||
globalArgumentName_ = n;
|
||||
if (n) {
|
||||
asmJSMetadata_->globalArgumentName = ParserAtomToNewUTF8CharsZ(cx_, n);
|
||||
MOZ_ASSERT(n->isTenured());
|
||||
asmJSMetadata_->globalArgumentName = StringToNewUTF8CharsZ(cx_, *n);
|
||||
if (!asmJSMetadata_->globalArgumentName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
MOZ_MUST_USE bool initImportArgumentName(const ParserName* n) {
|
||||
MOZ_MUST_USE bool initImportArgumentName(PropertyName* n) {
|
||||
importArgumentName_ = n;
|
||||
if (n) {
|
||||
asmJSMetadata_->importArgumentName = ParserAtomToNewUTF8CharsZ(cx_, n);
|
||||
MOZ_ASSERT(n->isTenured());
|
||||
asmJSMetadata_->importArgumentName = StringToNewUTF8CharsZ(cx_, *n);
|
||||
if (!asmJSMetadata_->importArgumentName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
MOZ_MUST_USE bool initBufferArgumentName(const ParserName* n) {
|
||||
MOZ_MUST_USE bool initBufferArgumentName(PropertyName* n) {
|
||||
bufferArgumentName_ = n;
|
||||
if (n) {
|
||||
asmJSMetadata_->bufferArgumentName = ParserAtomToNewUTF8CharsZ(cx_, n);
|
||||
MOZ_ASSERT(n->isTenured());
|
||||
asmJSMetadata_->bufferArgumentName = StringToNewUTF8CharsZ(cx_, *n);
|
||||
if (!asmJSMetadata_->bufferArgumentName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool addGlobalVarInit(const ParserName* var, const NumLit& lit, Type type,
|
||||
bool addGlobalVarInit(PropertyName* var, const NumLit& lit, Type type,
|
||||
bool isConst) {
|
||||
MOZ_ASSERT(type.isGlobalVarType());
|
||||
MOZ_ASSERT(type == Type::canonicalize(Type::lit(lit)));
|
||||
|
@ -1510,11 +1505,11 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.var.u.val_ = lit.value();
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addGlobalVarImport(const ParserName* var, const ParserName* field,
|
||||
Type type, bool isConst) {
|
||||
bool addGlobalVarImport(PropertyName* var, PropertyName* field, Type type,
|
||||
bool isConst) {
|
||||
MOZ_ASSERT(type.isGlobalVarType());
|
||||
|
||||
UniqueChars fieldChars = ParserAtomToNewUTF8CharsZ(cx_, field);
|
||||
UniqueChars fieldChars = StringToNewUTF8CharsZ(cx_, *field);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1541,11 +1536,11 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.var.u.importValType_ = valType.packed();
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addArrayView(const ParserName* var, Scalar::Type vt,
|
||||
const ParserName* maybeField) {
|
||||
bool addArrayView(PropertyName* var, Scalar::Type vt,
|
||||
PropertyName* maybeField) {
|
||||
UniqueChars fieldChars;
|
||||
if (maybeField) {
|
||||
fieldChars = ParserAtomToNewUTF8CharsZ(cx_, maybeField);
|
||||
fieldChars = StringToNewUTF8CharsZ(cx_, *maybeField);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1568,10 +1563,9 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.viewType_ = vt;
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addMathBuiltinFunction(const ParserName* var,
|
||||
AsmJSMathBuiltinFunction func,
|
||||
const ParserName* field) {
|
||||
UniqueChars fieldChars = ParserAtomToNewUTF8CharsZ(cx_, field);
|
||||
bool addMathBuiltinFunction(PropertyName* var, AsmJSMathBuiltinFunction func,
|
||||
PropertyName* field) {
|
||||
UniqueChars fieldChars = StringToNewUTF8CharsZ(cx_, *field);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1591,7 +1585,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
}
|
||||
|
||||
private:
|
||||
bool addGlobalDoubleConstant(const ParserName* var, double constant) {
|
||||
bool addGlobalDoubleConstant(PropertyName* var, double constant) {
|
||||
Global* global = validationLifo_.new_<Global>(Global::ConstantLiteral);
|
||||
if (!global) {
|
||||
return false;
|
||||
|
@ -1601,9 +1595,9 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
}
|
||||
|
||||
public:
|
||||
bool addMathBuiltinConstant(const ParserName* var, double constant,
|
||||
const ParserName* field) {
|
||||
UniqueChars fieldChars = ParserAtomToNewUTF8CharsZ(cx_, field);
|
||||
bool addMathBuiltinConstant(PropertyName* var, double constant,
|
||||
PropertyName* field) {
|
||||
UniqueChars fieldChars = StringToNewUTF8CharsZ(cx_, *field);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1617,9 +1611,9 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.constant.kind_ = AsmJSGlobal::MathConstant;
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addGlobalConstant(const ParserName* var, double constant,
|
||||
const ParserName* field) {
|
||||
UniqueChars fieldChars = ParserAtomToNewUTF8CharsZ(cx_, field);
|
||||
bool addGlobalConstant(PropertyName* var, double constant,
|
||||
PropertyName* field) {
|
||||
UniqueChars fieldChars = StringToNewUTF8CharsZ(cx_, *field);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1633,9 +1627,9 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.constant.kind_ = AsmJSGlobal::GlobalConstant;
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addArrayViewCtor(const ParserName* var, Scalar::Type vt,
|
||||
const ParserName* field) {
|
||||
UniqueChars fieldChars = ParserAtomToNewUTF8CharsZ(cx_, field);
|
||||
bool addArrayViewCtor(PropertyName* var, Scalar::Type vt,
|
||||
PropertyName* field) {
|
||||
UniqueChars fieldChars = StringToNewUTF8CharsZ(cx_, *field);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1653,8 +1647,8 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.viewType_ = vt;
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addFFI(const ParserName* var, const ParserName* field) {
|
||||
UniqueChars fieldChars = ParserAtomToNewUTF8CharsZ(cx_, field);
|
||||
bool addFFI(PropertyName* var, PropertyName* field) {
|
||||
UniqueChars fieldChars = StringToNewUTF8CharsZ(cx_, *field);
|
||||
if (!fieldChars) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1677,11 +1671,11 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
g.pod.u.ffiIndex_ = ffiIndex;
|
||||
return asmJSMetadata_->asmJSGlobals.append(std::move(g));
|
||||
}
|
||||
bool addExportField(const Func& func, const ParserName* maybeField) {
|
||||
bool addExportField(const Func& func, PropertyName* maybeField) {
|
||||
// Record the field name of this export.
|
||||
CacheableChars fieldChars;
|
||||
if (maybeField) {
|
||||
fieldChars = ParserAtomToNewUTF8CharsZ(cx_, maybeField);
|
||||
fieldChars = StringToNewUTF8CharsZ(cx_, *maybeField);
|
||||
} else {
|
||||
fieldChars = DuplicateString("");
|
||||
}
|
||||
|
@ -1783,17 +1777,16 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool failNameOffset(uint32_t offset, const char* fmt,
|
||||
const ParserName* name) {
|
||||
bool failNameOffset(uint32_t offset, const char* fmt, PropertyName* name) {
|
||||
// This function is invoked without the caller properly rooting its locals.
|
||||
gc::AutoSuppressGC suppress(cx_);
|
||||
if (UniqueChars bytes = ParserAtomToPrintableString(cx_, name)) {
|
||||
if (UniqueChars bytes = AtomToPrintableString(cx_, name)) {
|
||||
failfOffset(offset, fmt, bytes.get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool failName(ParseNode* pn, const char* fmt, const ParserName* name) {
|
||||
bool failName(ParseNode* pn, const char* fmt, PropertyName* name) {
|
||||
return failNameOffset(pn->pn_pos.begin, fmt, name);
|
||||
}
|
||||
|
||||
|
@ -1809,14 +1802,14 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
unsigned numFuncPtrTables() const { return tables_.length(); }
|
||||
Table& table(unsigned i) const { return *tables_[i]; }
|
||||
|
||||
const Global* lookupGlobal(const ParserName* name) const {
|
||||
const Global* lookupGlobal(PropertyName* name) const {
|
||||
if (GlobalMap::Ptr p = globalMap_.lookup(name)) {
|
||||
return p->value();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Func* lookupFuncDef(const ParserName* name) {
|
||||
Func* lookupFuncDef(PropertyName* name) {
|
||||
if (GlobalMap::Ptr p = globalMap_.lookup(name)) {
|
||||
Global* value = p->value();
|
||||
if (value->which() == Global::Function) {
|
||||
|
@ -1826,7 +1819,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool lookupStandardLibraryMathName(const ParserName* name,
|
||||
bool lookupStandardLibraryMathName(PropertyName* name,
|
||||
MathBuiltin* mathBuiltin) const {
|
||||
if (MathNameMap::Ptr p = standardLibraryMathNames_.lookup(name)) {
|
||||
*mathBuiltin = p->value();
|
||||
|
@ -1866,10 +1859,9 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
AsmJSParser<Unit>& parser_;
|
||||
|
||||
public:
|
||||
ModuleValidator(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
AsmJSParser<Unit>& parser, FunctionNode* moduleFunctionNode)
|
||||
: ModuleValidatorShared(cx, compilationInfo, moduleFunctionNode),
|
||||
parser_(parser) {}
|
||||
ModuleValidator(JSContext* cx, AsmJSParser<Unit>& parser,
|
||||
FunctionNode* moduleFunctionNode)
|
||||
: ModuleValidatorShared(cx, moduleFunctionNode), parser_(parser) {}
|
||||
|
||||
~ModuleValidator() {
|
||||
if (errorString_) {
|
||||
|
@ -1957,7 +1949,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
auto& tokenStream() const { return parser_.tokenStream; }
|
||||
|
||||
public:
|
||||
bool addFuncDef(const ParserName* name, uint32_t firstUse, FuncType&& sig,
|
||||
bool addFuncDef(PropertyName* name, uint32_t firstUse, FuncType&& sig,
|
||||
Func** func) {
|
||||
uint32_t sigIndex;
|
||||
if (!declareSig(std::move(sig), &sigIndex)) {
|
||||
|
@ -1983,7 +1975,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
*func = &funcDefs_.back();
|
||||
return true;
|
||||
}
|
||||
bool declareFuncPtrTable(FuncType&& sig, const ParserName* name,
|
||||
bool declareFuncPtrTable(FuncType&& sig, PropertyName* name,
|
||||
uint32_t firstUse, uint32_t mask,
|
||||
uint32_t* tableIndex) {
|
||||
if (mask > MaxTableLength) {
|
||||
|
@ -2022,7 +2014,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
Table* t = validationLifo_.new_<Table>(sigIndex, name, firstUse, mask);
|
||||
return t && tables_.append(t);
|
||||
}
|
||||
bool declareImport(const ParserName* name, FuncType&& sig, unsigned ffiIndex,
|
||||
bool declareImport(PropertyName* name, FuncType&& sig, unsigned ffiIndex,
|
||||
uint32_t* importIndex) {
|
||||
FuncImportMap::AddPtr p =
|
||||
funcImportMap_.lookupForAdd(NamedSig::Lookup(name, sig));
|
||||
|
@ -2084,7 +2076,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
return nullptr;
|
||||
}
|
||||
for (const Func& func : funcDefs_) {
|
||||
CacheableChars funcName = ParserAtomToNewUTF8CharsZ(cx_, func.name());
|
||||
CacheableChars funcName = StringToNewUTF8CharsZ(cx_, *func.name());
|
||||
if (!funcName ||
|
||||
!asmJSMetadata_->asmJSFuncNames.emplaceBack(std::move(funcName))) {
|
||||
return nullptr;
|
||||
|
@ -2311,7 +2303,7 @@ static inline bool IsLiteralInt(ModuleValidatorShared& m, ParseNode* pn,
|
|||
|
||||
namespace {
|
||||
|
||||
typedef Vector<const ParserName*, 4, SystemAllocPolicy> LabelVector;
|
||||
typedef Vector<PropertyName*, 4, SystemAllocPolicy> LabelVector;
|
||||
|
||||
class MOZ_STACK_CLASS FunctionValidatorShared {
|
||||
public:
|
||||
|
@ -2324,8 +2316,8 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
};
|
||||
|
||||
protected:
|
||||
using LocalMap = HashMap<const ParserName*, Local>;
|
||||
using LabelMap = HashMap<const ParserName*, uint32_t>;
|
||||
using LocalMap = HashMap<PropertyName*, Local>;
|
||||
using LabelMap = HashMap<PropertyName*, uint32_t>;
|
||||
|
||||
// This is also a ModuleValidator<Unit>& after the appropriate static_cast<>.
|
||||
ModuleValidatorShared& m_;
|
||||
|
@ -2390,13 +2382,13 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool failName(ParseNode* pn, const char* fmt, const ParserName* name) {
|
||||
bool failName(ParseNode* pn, const char* fmt, PropertyName* name) {
|
||||
return m_.failName(pn, fmt, name);
|
||||
}
|
||||
|
||||
/***************************************************** Local scope setup */
|
||||
|
||||
bool addLocal(ParseNode* pn, const ParserName* name, Type type) {
|
||||
bool addLocal(ParseNode* pn, PropertyName* name, Type type) {
|
||||
LocalMap::AddPtr p = locals_.lookupForAdd(name);
|
||||
if (p) {
|
||||
return failName(pn, "duplicate local name '%s' not allowed", name);
|
||||
|
@ -2424,7 +2416,7 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
return encoder().writeOp(op) &&
|
||||
encoder().writeVarU32(blockDepth_ - 1 - absolute);
|
||||
}
|
||||
void removeLabel(const ParserName* label, LabelMap* map) {
|
||||
void removeLabel(PropertyName* label, LabelMap* map) {
|
||||
LabelMap::Ptr p = map->lookup(label);
|
||||
MOZ_ASSERT(p);
|
||||
map->remove(p);
|
||||
|
@ -2443,7 +2435,7 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
|
||||
bool pushUnbreakableBlock(const LabelVector* labels = nullptr) {
|
||||
if (labels) {
|
||||
for (const ParserName* label : *labels) {
|
||||
for (PropertyName* label : *labels) {
|
||||
if (!breakLabels_.putNew(label, blockDepth_)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2455,7 +2447,7 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
}
|
||||
bool popUnbreakableBlock(const LabelVector* labels = nullptr) {
|
||||
if (labels) {
|
||||
for (const ParserName* label : *labels) {
|
||||
for (PropertyName* label : *labels) {
|
||||
removeLabel(label, &breakLabels_);
|
||||
}
|
||||
}
|
||||
|
@ -2523,7 +2515,7 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
|
||||
bool addLabels(const LabelVector& labels, uint32_t relativeBreakDepth,
|
||||
uint32_t relativeContinueDepth) {
|
||||
for (const ParserName* label : labels) {
|
||||
for (PropertyName* label : labels) {
|
||||
if (!breakLabels_.putNew(label, blockDepth_ + relativeBreakDepth)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2534,12 +2526,12 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
return true;
|
||||
}
|
||||
void removeLabels(const LabelVector& labels) {
|
||||
for (const ParserName* label : labels) {
|
||||
for (PropertyName* label : labels) {
|
||||
removeLabel(label, &breakLabels_);
|
||||
removeLabel(label, &continueLabels_);
|
||||
}
|
||||
}
|
||||
bool writeLabeledBreakOrContinue(const ParserName* label, bool isBreak) {
|
||||
bool writeLabeledBreakOrContinue(PropertyName* label, bool isBreak) {
|
||||
LabelMap& map = isBreak ? breakLabels_ : continueLabels_;
|
||||
if (LabelMap::Ptr p = map.lookup(label)) {
|
||||
return writeBr(p->value());
|
||||
|
@ -2549,15 +2541,14 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
|
|||
|
||||
/*************************************************** Read-only interface */
|
||||
|
||||
const Local* lookupLocal(const ParserName* name) const {
|
||||
const Local* lookupLocal(PropertyName* name) const {
|
||||
if (auto p = locals_.lookup(name)) {
|
||||
return &p->value();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ModuleValidatorShared::Global* lookupGlobal(
|
||||
const ParserName* name) const {
|
||||
const ModuleValidatorShared::Global* lookupGlobal(PropertyName* name) const {
|
||||
if (locals_.has(name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2642,7 +2633,7 @@ class MOZ_STACK_CLASS FunctionValidator : public FunctionValidatorShared {
|
|||
// asm.js type-checking and code-generation algorithm
|
||||
|
||||
static bool CheckIdentifier(ModuleValidatorShared& m, ParseNode* usepn,
|
||||
const ParserName* name) {
|
||||
PropertyName* name) {
|
||||
if (name == m.cx()->parserNames().arguments ||
|
||||
name == m.cx()->parserNames().eval) {
|
||||
return m.failName(usepn, "'%s' is not an allowed identifier", name);
|
||||
|
@ -2651,7 +2642,7 @@ static bool CheckIdentifier(ModuleValidatorShared& m, ParseNode* usepn,
|
|||
}
|
||||
|
||||
static bool CheckModuleLevelName(ModuleValidatorShared& m, ParseNode* usepn,
|
||||
const ParserName* name) {
|
||||
PropertyName* name) {
|
||||
if (!CheckIdentifier(m, usepn, name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2679,14 +2670,15 @@ static bool CheckFunctionHead(ModuleValidatorShared& m, FunctionNode* funNode) {
|
|||
}
|
||||
|
||||
static bool CheckArgument(ModuleValidatorShared& m, ParseNode* arg,
|
||||
const ParserName** name) {
|
||||
PropertyName** name) {
|
||||
*name = nullptr;
|
||||
|
||||
if (!arg->isKind(ParseNodeKind::Name)) {
|
||||
return m.fail(arg, "argument is not a plain name");
|
||||
}
|
||||
|
||||
const ParserName* argName = arg->as<NameNode>().name();
|
||||
PropertyName* argName = arg->as<NameNode>().name();
|
||||
;
|
||||
if (!CheckIdentifier(m, arg, argName)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2696,7 +2688,7 @@ static bool CheckArgument(ModuleValidatorShared& m, ParseNode* arg,
|
|||
}
|
||||
|
||||
static bool CheckModuleArgument(ModuleValidatorShared& m, ParseNode* arg,
|
||||
const ParserName** name) {
|
||||
PropertyName** name) {
|
||||
if (!CheckArgument(m, arg, name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2719,7 +2711,7 @@ static bool CheckModuleArguments(ModuleValidatorShared& m,
|
|||
return m.fail(funNode, "asm.js modules takes at most 3 argument");
|
||||
}
|
||||
|
||||
const ParserName* arg1Name = nullptr;
|
||||
PropertyName* arg1Name = nullptr;
|
||||
if (arg1 && !CheckModuleArgument(m, arg1, &arg1Name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2727,7 +2719,7 @@ static bool CheckModuleArguments(ModuleValidatorShared& m,
|
|||
return false;
|
||||
}
|
||||
|
||||
const ParserName* arg2Name = nullptr;
|
||||
PropertyName* arg2Name = nullptr;
|
||||
if (arg2 && !CheckModuleArgument(m, arg2, &arg2Name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2735,7 +2727,7 @@ static bool CheckModuleArguments(ModuleValidatorShared& m,
|
|||
return false;
|
||||
}
|
||||
|
||||
const ParserName* arg3Name = nullptr;
|
||||
PropertyName* arg3Name = nullptr;
|
||||
if (arg3 && !CheckModuleArgument(m, arg3, &arg3Name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2761,7 +2753,7 @@ static bool CheckPrecedingStatements(ModuleValidatorShared& m,
|
|||
}
|
||||
|
||||
static bool CheckGlobalVariableInitConstant(ModuleValidatorShared& m,
|
||||
const ParserName* varName,
|
||||
PropertyName* varName,
|
||||
ParseNode* initNode, bool isConst) {
|
||||
NumLit lit = ExtractNumericLiteral(m, initNode);
|
||||
if (!lit.valid()) {
|
||||
|
@ -2813,7 +2805,7 @@ static bool CheckTypeAnnotation(ModuleValidatorShared& m,
|
|||
}
|
||||
|
||||
static bool CheckGlobalVariableInitImport(ModuleValidatorShared& m,
|
||||
const ParserName* varName,
|
||||
PropertyName* varName,
|
||||
ParseNode* initNode, bool isConst) {
|
||||
Type coerceTo;
|
||||
ParseNode* coercedExpr;
|
||||
|
@ -2831,9 +2823,9 @@ static bool CheckGlobalVariableInitImport(ModuleValidatorShared& m,
|
|||
}
|
||||
|
||||
ParseNode* base = DotBase(coercedExpr);
|
||||
const ParserName* field = DotMember(coercedExpr);
|
||||
PropertyName* field = DotMember(coercedExpr);
|
||||
|
||||
const ParserName* importName = m.importArgumentName();
|
||||
PropertyName* importName = m.importArgumentName();
|
||||
if (!importName) {
|
||||
return m.fail(coercedExpr,
|
||||
"cannot import without an asm.js foreign parameter");
|
||||
|
@ -2846,9 +2838,9 @@ static bool CheckGlobalVariableInitImport(ModuleValidatorShared& m,
|
|||
return m.addGlobalVarImport(varName, field, coerceTo, isConst);
|
||||
}
|
||||
|
||||
static bool IsArrayViewCtorName(ModuleValidatorShared& m,
|
||||
const ParserName* name, Scalar::Type* type) {
|
||||
js::frontend::WellKnownParserAtoms& names = m.cx()->parserNames();
|
||||
static bool IsArrayViewCtorName(ModuleValidatorShared& m, PropertyName* name,
|
||||
Scalar::Type* type) {
|
||||
JSAtomState& names = m.cx()->parserNames();
|
||||
if (name == names.Int8Array) {
|
||||
*type = Scalar::Int8;
|
||||
} else if (name == names.Uint8Array) {
|
||||
|
@ -2872,7 +2864,7 @@ static bool IsArrayViewCtorName(ModuleValidatorShared& m,
|
|||
}
|
||||
|
||||
static bool CheckNewArrayViewArgs(ModuleValidatorShared& m, ParseNode* newExpr,
|
||||
const ParserName* bufferName) {
|
||||
PropertyName* bufferName) {
|
||||
ParseNode* ctorExpr = BinaryLeft(newExpr);
|
||||
ParseNode* ctorArgs = BinaryRight(newExpr);
|
||||
ParseNode* bufArg = ListHead(ctorArgs);
|
||||
|
@ -2889,15 +2881,15 @@ static bool CheckNewArrayViewArgs(ModuleValidatorShared& m, ParseNode* newExpr,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool CheckNewArrayView(ModuleValidatorShared& m,
|
||||
const ParserName* varName, ParseNode* newExpr) {
|
||||
const ParserName* globalName = m.globalArgumentName();
|
||||
static bool CheckNewArrayView(ModuleValidatorShared& m, PropertyName* varName,
|
||||
ParseNode* newExpr) {
|
||||
PropertyName* globalName = m.globalArgumentName();
|
||||
if (!globalName) {
|
||||
return m.fail(
|
||||
newExpr, "cannot create array view without an asm.js global parameter");
|
||||
}
|
||||
|
||||
const ParserName* bufferName = m.bufferArgumentName();
|
||||
PropertyName* bufferName = m.bufferArgumentName();
|
||||
if (!bufferName) {
|
||||
return m.fail(newExpr,
|
||||
"cannot create array view without an asm.js heap parameter");
|
||||
|
@ -2905,7 +2897,7 @@ static bool CheckNewArrayView(ModuleValidatorShared& m,
|
|||
|
||||
ParseNode* ctorExpr = BinaryLeft(newExpr);
|
||||
|
||||
const ParserName* field;
|
||||
PropertyName* field;
|
||||
Scalar::Type type;
|
||||
if (ctorExpr->isKind(ParseNodeKind::DotExpr)) {
|
||||
ParseNode* base = DotBase(ctorExpr);
|
||||
|
@ -2924,7 +2916,7 @@ static bool CheckNewArrayView(ModuleValidatorShared& m,
|
|||
"expecting name of imported array view constructor");
|
||||
}
|
||||
|
||||
const ParserName* globalName = ctorExpr->as<NameNode>().name();
|
||||
PropertyName* globalName = ctorExpr->as<NameNode>().name();
|
||||
const ModuleValidatorShared::Global* global = m.lookupGlobal(globalName);
|
||||
if (!global) {
|
||||
return m.failName(ctorExpr, "%s not found in module global scope",
|
||||
|
@ -2949,8 +2941,7 @@ static bool CheckNewArrayView(ModuleValidatorShared& m,
|
|||
}
|
||||
|
||||
static bool CheckGlobalMathImport(ModuleValidatorShared& m, ParseNode* initNode,
|
||||
const ParserName* varName,
|
||||
const ParserName* field) {
|
||||
PropertyName* varName, PropertyName* field) {
|
||||
// Math builtin, with the form glob.Math.[[builtin]]
|
||||
ModuleValidatorShared::MathBuiltin mathBuiltin;
|
||||
if (!m.lookupStandardLibraryMathName(field, &mathBuiltin)) {
|
||||
|
@ -2969,16 +2960,15 @@ static bool CheckGlobalMathImport(ModuleValidatorShared& m, ParseNode* initNode,
|
|||
}
|
||||
|
||||
static bool CheckGlobalDotImport(ModuleValidatorShared& m,
|
||||
const ParserName* varName,
|
||||
ParseNode* initNode) {
|
||||
PropertyName* varName, ParseNode* initNode) {
|
||||
ParseNode* base = DotBase(initNode);
|
||||
const ParserName* field = DotMember(initNode);
|
||||
PropertyName* field = DotMember(initNode);
|
||||
|
||||
if (base->isKind(ParseNodeKind::DotExpr)) {
|
||||
ParseNode* global = DotBase(base);
|
||||
const ParserName* math = DotMember(base);
|
||||
PropertyName* math = DotMember(base);
|
||||
|
||||
const ParserName* globalName = m.globalArgumentName();
|
||||
PropertyName* globalName = m.globalArgumentName();
|
||||
if (!globalName) {
|
||||
return m.fail(
|
||||
base, "import statement requires the module have a stdlib parameter");
|
||||
|
@ -3042,7 +3032,7 @@ static bool CheckModuleGlobal(ModuleValidatorShared& m, ParseNode* decl,
|
|||
return m.fail(var, "import variable is not a plain name");
|
||||
}
|
||||
|
||||
const ParserName* varName = var->as<NameNode>().name();
|
||||
PropertyName* varName = var->as<NameNode>().name();
|
||||
if (!CheckModuleLevelName(m, var, varName)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3119,7 +3109,7 @@ static bool CheckModuleGlobals(ModuleValidator<Unit>& m) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool ArgFail(FunctionValidatorShared& f, const ParserName* argName,
|
||||
static bool ArgFail(FunctionValidatorShared& f, PropertyName* argName,
|
||||
ParseNode* stmt) {
|
||||
return f.failName(stmt,
|
||||
"expecting argument type declaration for '%s' of the "
|
||||
|
@ -3128,7 +3118,7 @@ static bool ArgFail(FunctionValidatorShared& f, const ParserName* argName,
|
|||
}
|
||||
|
||||
static bool CheckArgumentType(FunctionValidatorShared& f, ParseNode* stmt,
|
||||
const ParserName* name, Type* type) {
|
||||
PropertyName* name, Type* type) {
|
||||
if (!stmt || !IsExpressionStatement(stmt)) {
|
||||
return ArgFail(f, name, stmt ? stmt : f.fn());
|
||||
}
|
||||
|
@ -3182,7 +3172,7 @@ static bool CheckArguments(FunctionValidatorShared& f, ParseNode** stmtIter,
|
|||
|
||||
for (unsigned i = 0; i < numFormals;
|
||||
i++, argpn = NextNode(argpn), stmt = NextNode(stmt)) {
|
||||
const ParserName* name = nullptr;
|
||||
PropertyName* name;
|
||||
if (!CheckArgument(f.m(), argpn, &name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3262,7 +3252,7 @@ static bool CheckVariable(FunctionValidatorShared& f, ParseNode* decl,
|
|||
return f.fail(var, "local variable is not a plain name");
|
||||
}
|
||||
|
||||
const ParserName* name = var->as<NameNode>().name();
|
||||
PropertyName* name = var->as<NameNode>().name();
|
||||
|
||||
if (!CheckIdentifier(f.m(), var, name)) {
|
||||
return false;
|
||||
|
@ -3345,7 +3335,7 @@ static bool CheckNumericLiteral(FunctionValidator<Unit>& f, ParseNode* num,
|
|||
|
||||
static bool CheckVarRef(FunctionValidatorShared& f, ParseNode* varRef,
|
||||
Type* type) {
|
||||
const ParserName* name = varRef->as<NameNode>().name();
|
||||
PropertyName* name = varRef->as<NameNode>().name();
|
||||
|
||||
if (const FunctionValidatorShared::Local* local = f.lookupLocal(name)) {
|
||||
if (!f.encoder().writeOp(Op::GetLocal)) {
|
||||
|
@ -3661,7 +3651,7 @@ static bool CheckStoreArray(FunctionValidator<Unit>& f, ParseNode* lhs,
|
|||
template <typename Unit>
|
||||
static bool CheckAssignName(FunctionValidator<Unit>& f, ParseNode* lhs,
|
||||
ParseNode* rhs, Type* type) {
|
||||
const ParserName* name = lhs->as<NameNode>().name();
|
||||
RootedPropertyName name(f.cx(), lhs->as<NameNode>().name());
|
||||
|
||||
if (const FunctionValidatorShared::Local* lhsVar = f.lookupLocal(name)) {
|
||||
Type rhsType;
|
||||
|
@ -3943,7 +3933,7 @@ static bool CheckSignatureAgainstExisting(ModuleValidatorShared& m,
|
|||
|
||||
template <typename Unit>
|
||||
static bool CheckFunctionSignature(ModuleValidator<Unit>& m, ParseNode* usepn,
|
||||
FuncType&& sig, const ParserName* name,
|
||||
FuncType&& sig, PropertyName* name,
|
||||
ModuleValidatorShared::Func** func) {
|
||||
if (sig.args().length() > MaxParams) {
|
||||
return m.failf(usepn, "too many parameters");
|
||||
|
@ -3979,8 +3969,7 @@ static bool CheckIsArgType(FunctionValidatorShared& f, ParseNode* argNode,
|
|||
|
||||
template <typename Unit>
|
||||
static bool CheckInternalCall(FunctionValidator<Unit>& f, ParseNode* callNode,
|
||||
const ParserName* calleeName, Type ret,
|
||||
Type* type) {
|
||||
PropertyName* calleeName, Type ret, Type* type) {
|
||||
MOZ_ASSERT(ret.isCanonical());
|
||||
|
||||
ValTypeVector args;
|
||||
|
@ -4017,8 +4006,8 @@ static bool CheckInternalCall(FunctionValidator<Unit>& f, ParseNode* callNode,
|
|||
template <typename Unit>
|
||||
static bool CheckFuncPtrTableAgainstExisting(ModuleValidator<Unit>& m,
|
||||
ParseNode* usepn,
|
||||
const ParserName* name,
|
||||
FuncType&& sig, unsigned mask,
|
||||
PropertyName* name, FuncType&& sig,
|
||||
unsigned mask,
|
||||
uint32_t* tableIndex) {
|
||||
if (const ModuleValidatorShared::Global* existing = m.lookupGlobal(name)) {
|
||||
if (existing->which() != ModuleValidatorShared::Global::Table) {
|
||||
|
@ -4065,7 +4054,7 @@ static bool CheckFuncPtrCall(FunctionValidator<Unit>& f, ParseNode* callNode,
|
|||
return f.fail(tableNode, "expecting name of function-pointer array");
|
||||
}
|
||||
|
||||
const ParserName* name = tableNode->as<NameNode>().name();
|
||||
PropertyName* name = tableNode->as<NameNode>().name();
|
||||
if (const ModuleValidatorShared::Global* existing = f.lookupGlobal(name)) {
|
||||
if (existing->which() != ModuleValidatorShared::Global::Table) {
|
||||
return f.failName(
|
||||
|
@ -4144,7 +4133,7 @@ static bool CheckFFICall(FunctionValidator<Unit>& f, ParseNode* callNode,
|
|||
unsigned ffiIndex, Type ret, Type* type) {
|
||||
MOZ_ASSERT(ret.isCanonical());
|
||||
|
||||
const ParserName* calleeName = CallCallee(callNode)->as<NameNode>().name();
|
||||
PropertyName* calleeName = CallCallee(callNode)->as<NameNode>().name();
|
||||
|
||||
if (ret.isFloat()) {
|
||||
return f.fail(callNode, "FFI calls can't return float");
|
||||
|
@ -4511,7 +4500,7 @@ static bool CheckCoercedCall(FunctionValidator<Unit>& f, ParseNode* call,
|
|||
return f.fail(callee, "unexpected callee expression type");
|
||||
}
|
||||
|
||||
const ParserName* calleeName = callee->as<NameNode>().name();
|
||||
PropertyName* calleeName = callee->as<NameNode>().name();
|
||||
|
||||
if (const ModuleValidatorShared::Global* global =
|
||||
f.lookupGlobal(calleeName)) {
|
||||
|
@ -5939,7 +5928,7 @@ static bool CheckLexicalScope(FunctionValidator<Unit>& f, ParseNode* node) {
|
|||
|
||||
static bool CheckBreakOrContinue(FunctionValidatorShared& f, bool isBreak,
|
||||
ParseNode* stmt) {
|
||||
if (const ParserName* maybeLabel = LoopControlMaybeLabel(stmt)) {
|
||||
if (PropertyName* maybeLabel = LoopControlMaybeLabel(stmt)) {
|
||||
return f.writeLabeledBreakOrContinue(maybeLabel, isBreak);
|
||||
}
|
||||
return f.writeUnlabeledBreakOrContinue(isBreak);
|
||||
|
@ -6008,7 +5997,7 @@ static bool ParseFunction(ModuleValidator<Unit>& m, FunctionNode** funNodeOut,
|
|||
// m.fail.
|
||||
}
|
||||
|
||||
const ParserName* name = m.parser().bindingIdentifier(YieldIsName);
|
||||
RootedPropertyName name(m.cx(), m.parser().bindingIdentifier(YieldIsName));
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
@ -6196,7 +6185,7 @@ static bool CheckFuncPtrTable(ModuleValidator<Unit>& m, ParseNode* decl) {
|
|||
elem, "function-pointer table's elements must be names of functions");
|
||||
}
|
||||
|
||||
const ParserName* funcName = elem->as<NameNode>().name();
|
||||
PropertyName* funcName = elem->as<NameNode>().name();
|
||||
const ModuleValidatorShared::Func* func = m.lookupFuncDef(funcName);
|
||||
if (!func) {
|
||||
return m.fail(
|
||||
|
@ -6264,14 +6253,13 @@ static bool CheckFuncPtrTables(ModuleValidator<Unit>& m) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool CheckModuleExportFunction(
|
||||
ModuleValidatorShared& m, ParseNode* pn,
|
||||
const ParserName* maybeFieldName = nullptr) {
|
||||
static bool CheckModuleExportFunction(ModuleValidatorShared& m, ParseNode* pn,
|
||||
PropertyName* maybeFieldName = nullptr) {
|
||||
if (!pn->isKind(ParseNodeKind::Name)) {
|
||||
return m.fail(pn, "expected name of exported function");
|
||||
}
|
||||
|
||||
const ParserName* funcName = pn->as<NameNode>().name();
|
||||
PropertyName* funcName = pn->as<NameNode>().name();
|
||||
const ModuleValidatorShared::Func* func = m.lookupFuncDef(funcName);
|
||||
if (!func) {
|
||||
return m.failName(pn, "function '%s' not found", funcName);
|
||||
|
@ -6291,7 +6279,7 @@ static bool CheckModuleExportObject(ModuleValidatorShared& m,
|
|||
"object literal");
|
||||
}
|
||||
|
||||
const ParserName* fieldName = ObjectNormalFieldName(pn);
|
||||
PropertyName* fieldName = ObjectNormalFieldName(pn);
|
||||
|
||||
ParseNode* initNode = ObjectNormalFieldInitializer(pn);
|
||||
if (!initNode->isKind(ParseNodeKind::Name)) {
|
||||
|
@ -6363,14 +6351,13 @@ static bool CheckModuleEnd(ModuleValidator<Unit>& m) {
|
|||
}
|
||||
|
||||
template <typename Unit>
|
||||
static SharedModule CheckModule(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
AsmJSParser<Unit>& parser, ParseNode* stmtList,
|
||||
unsigned* time) {
|
||||
static SharedModule CheckModule(JSContext* cx, AsmJSParser<Unit>& parser,
|
||||
ParseNode* stmtList, unsigned* time) {
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
FunctionNode* moduleFunctionNode = parser.pc_->functionBox()->functionNode;
|
||||
|
||||
ModuleValidator<Unit> m(cx, compilationInfo, parser, moduleFunctionNode);
|
||||
ModuleValidator<Unit> m(cx, parser, moduleFunctionNode);
|
||||
if (!m.init()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -7058,9 +7045,8 @@ static bool EstablishPreconditions(JSContext* cx,
|
|||
}
|
||||
|
||||
template <typename Unit>
|
||||
static bool DoCompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
AsmJSParser<Unit>& parser, ParseNode* stmtList,
|
||||
bool* validated) {
|
||||
static bool DoCompileAsmJS(JSContext* cx, AsmJSParser<Unit>& parser,
|
||||
ParseNode* stmtList, bool* validated) {
|
||||
*validated = false;
|
||||
|
||||
// Various conditions disable asm.js optimizations.
|
||||
|
@ -7071,8 +7057,7 @@ static bool DoCompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo,
|
|||
// "Checking" parses, validates and compiles, producing a fully compiled
|
||||
// WasmModuleObject as result.
|
||||
unsigned time;
|
||||
SharedModule module =
|
||||
CheckModule(cx, compilationInfo, parser, stmtList, &time);
|
||||
SharedModule module = CheckModule(cx, parser, stmtList, &time);
|
||||
if (!module) {
|
||||
return NoExceptionPending(cx);
|
||||
}
|
||||
|
@ -7092,16 +7077,14 @@ static bool DoCompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo,
|
|||
return NoExceptionPending(cx);
|
||||
}
|
||||
|
||||
bool js::CompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
AsmJSParser<char16_t>& parser, ParseNode* stmtList,
|
||||
bool* validated) {
|
||||
return DoCompileAsmJS(cx, compilationInfo, parser, stmtList, validated);
|
||||
bool js::CompileAsmJS(JSContext* cx, AsmJSParser<char16_t>& parser,
|
||||
ParseNode* stmtList, bool* validated) {
|
||||
return DoCompileAsmJS(cx, parser, stmtList, validated);
|
||||
}
|
||||
|
||||
bool js::CompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
AsmJSParser<Utf8Unit>& parser, ParseNode* stmtList,
|
||||
bool* validated) {
|
||||
return DoCompileAsmJS(cx, compilationInfo, parser, stmtList, validated);
|
||||
bool js::CompileAsmJS(JSContext* cx, AsmJSParser<Utf8Unit>& parser,
|
||||
ParseNode* stmtList, bool* validated) {
|
||||
return DoCompileAsmJS(cx, parser, stmtList, validated);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -43,8 +43,6 @@ namespace js {
|
|||
|
||||
namespace frontend {
|
||||
|
||||
struct CompilationInfo;
|
||||
|
||||
class ParseContext;
|
||||
class ParseNode;
|
||||
|
||||
|
@ -64,14 +62,14 @@ using AsmJSParser = frontend::Parser<frontend::FullParseHandler, Unit>;
|
|||
// indeterminate amount and the entire function should be reparsed from the
|
||||
// beginning.
|
||||
|
||||
extern MOZ_MUST_USE bool CompileAsmJS(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
AsmJSParser<mozilla::Utf8Unit>& parser, frontend::ParseNode* stmtList,
|
||||
extern MOZ_MUST_USE bool CompileAsmJS(JSContext* cx,
|
||||
AsmJSParser<mozilla::Utf8Unit>& parser,
|
||||
frontend::ParseNode* stmtList,
|
||||
bool* validated);
|
||||
|
||||
extern MOZ_MUST_USE bool CompileAsmJS(
|
||||
JSContext* cx, frontend::CompilationInfo& compilationInfo,
|
||||
AsmJSParser<char16_t>& parser, frontend::ParseNode* stmtList,
|
||||
extern MOZ_MUST_USE bool CompileAsmJS(JSContext* cx,
|
||||
AsmJSParser<char16_t>& parser,
|
||||
frontend::ParseNode* stmtList,
|
||||
bool* validated);
|
||||
|
||||
// asm.js module/export queries:
|
||||
|
|
Загрузка…
Ссылка в новой задаче