From f66ec87fd8f259618da6f66bf240fe5af91d3a07 Mon Sep 17 00:00:00 2001 From: Cosmin Sabou Date: Tue, 25 Aug 2020 01:03:43 +0300 Subject: [PATCH] Backed out 2 changesets (bug 1660798) for causing memory leaks. CLOSED TREE Backed out changeset 846f88debca6 (bug 1660798) Backed out changeset 12d099efac67 (bug 1660798) --- js/moz.configure | 6 + js/src/builtin/ModuleObject.cpp | 135 ++-- js/src/builtin/ReflectParse.cpp | 55 +- js/src/frontend/BCEParserHandle.h | 1 - js/src/frontend/BytecodeCompiler.h | 4 - js/src/frontend/BytecodeControlStructures.cpp | 4 +- js/src/frontend/BytecodeControlStructures.h | 10 +- js/src/frontend/BytecodeEmitter.cpp | 198 +++--- js/src/frontend/BytecodeEmitter.h | 54 +- js/src/frontend/BytecodeSection.cpp | 15 +- js/src/frontend/BytecodeSection.h | 2 +- js/src/frontend/CallOrNewEmitter.cpp | 2 +- js/src/frontend/CallOrNewEmitter.h | 2 +- js/src/frontend/CompilationInfo.h | 8 - js/src/frontend/EitherParser.h | 9 - js/src/frontend/EmitterScope.cpp | 74 +-- js/src/frontend/EmitterScope.h | 18 +- js/src/frontend/FoldConstants.cpp | 65 +- js/src/frontend/Frontend2.cpp | 69 +-- js/src/frontend/FullParseHandler.h | 35 +- js/src/frontend/FunctionEmitter.cpp | 17 +- js/src/frontend/FunctionEmitter.h | 10 +- js/src/frontend/LabelEmitter.cpp | 2 +- js/src/frontend/LabelEmitter.h | 2 +- js/src/frontend/LexicalScopeEmitter.cpp | 2 +- js/src/frontend/LexicalScopeEmitter.h | 3 +- js/src/frontend/ModuleSharedContext.h | 2 +- js/src/frontend/NameAnalysisTypes.h | 3 +- js/src/frontend/NameCollections.h | 4 +- js/src/frontend/NameFunctions.cpp | 46 +- js/src/frontend/NameFunctions.h | 4 +- js/src/frontend/NameOpEmitter.cpp | 4 +- js/src/frontend/NameOpEmitter.h | 6 +- js/src/frontend/ObjLiteral.cpp | 72 +-- js/src/frontend/ObjLiteral.h | 19 +- js/src/frontend/ObjectEmitter.cpp | 32 +- js/src/frontend/ObjectEmitter.h | 23 +- js/src/frontend/ParseContext-inl.h | 4 +- js/src/frontend/ParseContext.cpp | 55 +- js/src/frontend/ParseContext.h | 38 +- js/src/frontend/ParseNode.cpp | 36 +- js/src/frontend/ParseNode.h | 67 +- js/src/frontend/Parser.cpp | 574 ++++++++---------- js/src/frontend/Parser.h | 179 +++--- js/src/frontend/ParserAtom.cpp | 81 ++- js/src/frontend/ParserAtom.h | 38 +- js/src/frontend/PropOpEmitter.cpp | 10 +- js/src/frontend/PropOpEmitter.h | 11 +- js/src/frontend/SharedContext-inl.h | 7 - js/src/frontend/SharedContext.cpp | 12 +- js/src/frontend/SharedContext.h | 67 +- js/src/frontend/Stencil.cpp | 125 ++-- js/src/frontend/Stencil.h | 94 ++- js/src/frontend/SwitchEmitter.cpp | 2 +- js/src/frontend/SwitchEmitter.h | 2 +- js/src/frontend/SyntaxParseHandler.h | 29 +- js/src/frontend/TDZCheckCache.cpp | 4 +- js/src/frontend/TDZCheckCache.h | 4 +- js/src/frontend/Token.h | 20 +- js/src/frontend/TokenStream.cpp | 75 +-- js/src/frontend/TokenStream.h | 77 ++- js/src/frontend/UsedNameTracker.h | 15 +- js/src/jsapi.cpp | 2 - js/src/jsnum.cpp | 41 -- js/src/jsnum.h | 13 - js/src/util/StringBuffer.cpp | 42 -- js/src/util/StringBuffer.h | 10 - js/src/vm/BuiltinObjectKind.cpp | 39 +- js/src/vm/BuiltinObjectKind.h | 10 +- js/src/vm/GeneratorObject.cpp | 12 +- js/src/vm/GeneratorObject.h | 9 +- js/src/vm/Instrumentation.cpp | 14 +- js/src/vm/Instrumentation.h | 9 +- js/src/vm/JSContext.h | 8 +- js/src/vm/ModuleBuilder.h | 23 +- js/src/vm/Printer.cpp | 21 - js/src/vm/Printer.h | 16 - js/src/vm/Scope.cpp | 542 ++++++----------- js/src/vm/Scope.h | 192 +++--- js/src/vm/SelfHosting.cpp | 11 - js/src/vm/SelfHosting.h | 5 - js/src/vm/StringType.cpp | 9 - js/src/vm/StringType.h | 9 - js/src/wasm/AsmJS.cpp | 341 +++++------ js/src/wasm/AsmJS.h | 18 +- 85 files changed, 1662 insertions(+), 2377 deletions(-) diff --git a/js/moz.configure b/js/moz.configure index 7cd95edf25f3..a4024d613983 100644 --- a/js/moz.configure +++ b/js/moz.configure @@ -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 # ================================================================== diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 1466114b6235..dacdb89d7b38 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -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 module) { + JSContext* cx, JS::Handle 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(); 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(); MOZ_ASSERT(spec->isKind(ParseNodeKind::ImportSpec)); NameNode* importNameNode = &spec->left()->as(); + NameNode* localNameNode = &spec->right()->as(); - 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().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().contents()) { BinaryNode* spec = &item->as(); MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportSpec)); NameNode* localNameNode = &spec->left()->as(); NameNode* exportNameNode = &spec->right()->as(); - - 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(); 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().contents()) { if (binding->isKind(ParseNodeKind::AssignExpr)) { binding = binding->as().left(); @@ -1506,10 +1479,8 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) { } if (binding->isKind(ParseNodeKind::Name)) { - const frontend::ParserAtom* localName = - binding->as().atom(); - const frontend::ParserAtom* exportName = - isDefault ? cx_->parserNames().default_ : localName; + localName = binding->as().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().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().atom(); + RootedAtom name(cx_, binding->as().atom()); return appendExportEntry(name, name); } @@ -1631,28 +1603,27 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) { NameNode* moduleSpec = &exportNode->right()->as(); 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().left()->as(); NameNode* exportNameNode = &spec->as().right()->as(); - - 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; } diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index cd638ea9ea74..4e4e93db039e 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -2473,13 +2473,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) { case ParseNodeKind::ContinueStmt: { LoopControlStatement* node = &pn->as(); 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(); 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().atom()); - if (!exprAtom) { - return false; - } - expr.setString(exprAtom); + expr.setString(cookedItem->as().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().atom()); - if (!exprAtom) { - return false; - } - val.setString(exprAtom); + case ParseNodeKind::StringExpr: + val.setString(pn->as().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; } diff --git a/js/src/frontend/BCEParserHandle.h b/js/src/frontend/BCEParserHandle.h index 4abb5a6f6604..218b90021f65 100644 --- a/js/src/frontend/BCEParserHandle.h +++ b/js/src/frontend/BCEParserHandle.h @@ -10,7 +10,6 @@ #include "frontend/ErrorReporter.h" #include "frontend/FullParseHandler.h" #include "frontend/Parser.h" -#include "frontend/ParserAtom.h" namespace js { namespace frontend { diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h index aacc517ec5be..4a89ac5f387f 100644 --- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -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 { diff --git a/js/src/frontend/BytecodeControlStructures.cpp b/js/src/frontend/BytecodeControlStructures.cpp index 401e27d8b22c..2b650fb5e20a 100644 --- a/js/src/frontend/BytecodeControlStructures.cpp +++ b/js/src/frontend/BytecodeControlStructures.cpp @@ -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) diff --git a/js/src/frontend/BytecodeControlStructures.h b/js/src/frontend/BytecodeControlStructures.h index a86163ac55ad..b8a28718a0a5 100644 --- a/js/src/frontend/BytecodeControlStructures.h +++ b/js/src/frontend/BytecodeControlStructures.h @@ -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() 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_; } }; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 088bd5cfe4d0..d6b04e97687b 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -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(innermostNestableControl, predicate); } -NameLocation BytecodeEmitter::lookupName(const ParserAtom* name) { +NameLocation BytecodeEmitter::lookupName(JSAtom* name) { return innermostEmitterScope()->lookup(this, name); } Maybe BytecodeEmitter::locationOfNameBoundInScope( - const ParserAtom* name, EmitterScope* target) { + JSAtom* name, EmitterScope* target) { return innermostEmitterScope()->locationBoundInScope(name, target); } Maybe BytecodeEmitter::locationOfNameBoundInFunctionScope( - const ParserAtom* name, EmitterScope* source) { + JSAtom* name, EmitterScope* source) { EmitterScope* funScope = source; while (!funScope->scope(this).is()) { 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 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(); - 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().name(); + RootedAtom name(cx, setThisNode->left()->as().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 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().name(); + RootedAtom name(cx, target->as().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()) { @@ -3139,7 +3139,7 @@ bool BytecodeEmitter::emitAnonymousFunctionWithComputedName( return emitClass(&node->as(), 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().name(); + RootedAtom name(cx, pattern->as().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().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().atom(); + pnatom.set(key->as().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().atom()->length() == 0) { + if (isString && item->as().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 noe; Maybe 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(); 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 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().atom()); + AtomToResumeKind(cx, kindNode->as().atom()); MOZ_ASSERT(!kindNode->pn_next); if (!emitPushResumeKind(kind)) { @@ -7347,7 +7346,7 @@ bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype( return false; } - const ParserAtom* name = argNode->as().atom(); + JSAtom* name = argNode->as().atom(); BuiltinObjectKind kind; if (isConstructor) { @@ -7440,14 +7439,14 @@ bool BytecodeEmitter::isRestParameter(ParseNode* expr) { expr->as().right()->as().head()); } - const ParserAtom* name = expr->as().name(); + JSAtom* name = expr->as().name(); Maybe 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().name(); + RootedAtom nameAtom(cx, callee->as().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().name(); + RootedAtom nameAtom(cx, callee->as().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().name(); + RootedPropertyName calleeName(cx, calleeNode->as().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(); 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().toAtom(compilationInfo); + RootedAtom keyAtom(cx, key->as().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().atom(); + RootedAtom keyAtom(cx, key->as().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().atom(); + RootedAtom keyAtom(cx, key->as().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().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().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().name(); + RootedAtom paramName(cx, bindingElement->as().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().name(); + RootedAtom paramName(cx, bindingElement->as().name()); if (!fpe.emitDefaultEnd(paramName)) { // [stack] return false; @@ -10021,7 +10022,7 @@ bool BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody) { continue; } - const ParserAtom* paramName = bindingElement->as().name(); + RootedAtom paramName(cx, bindingElement->as().name()); if (!fpe.emitSimple(paramName)) { // [stack] return false; @@ -10036,32 +10037,32 @@ bool BytecodeEmitter::emitInitializeFunctionSpecialNames() { // [stack] - auto emitInitializeFunctionSpecialName = [](BytecodeEmitter* bce, - const ParserName* name, JSOp op) { - // A special name must be slotful, either on the frame or on the - // call environment. - MOZ_ASSERT(bce->lookupName(name).hasKnownSlot()); + 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()); - NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize); - if (!noe.prepareForRhs()) { - // [stack] - return false; - } - if (!bce->emit1(op)) { - // [stack] THIS/ARGUMENTS - return false; - } - if (!noe.emitAssignment()) { - // [stack] THIS/ARGUMENTS - return false; - } - if (!bce->emit1(JSOp::Pop)) { - // [stack] - return false; - } + NameOpEmitter noe(bce, name, NameOpEmitter::Kind::Initialize); + if (!noe.prepareForRhs()) { + // [stack] + return false; + } + if (!bce->emit1(op)) { + // [stack] THIS/ARGUMENTS + return false; + } + if (!noe.emitAssignment()) { + // [stack] THIS/ARGUMENTS + return false; + } + if (!bce->emit1(JSOp::Pop)) { + // [stack] + return false; + } - return true; - }; + return true; + }; // Do nothing if the function doesn't have an arguments binding. if (funbox->argumentsHasVarBinding()) { @@ -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 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().name(); + RootedAtom privateName(cx, elementName->as().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; } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 81e5502a497e..ca69c71d368e 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -209,22 +209,22 @@ struct MOZ_STACK_CLASS BytecodeEmitter { template 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 locationOfNameBoundInScope( - const ParserAtom* name, EmitterScope* target); + mozilla::Maybe 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 locationOfNameBoundInFunctionScope( - const ParserAtom* name, EmitterScope* source); + JSAtom* name, EmitterScope* source); mozilla::Maybe 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 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 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 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 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 nameForAnonymousClass = nullptr); MOZ_MUST_USE bool emitSuperElemOperands( PropertyByValue* elem, EmitElemOption opts = EmitElemOption::Get); MOZ_MUST_USE bool emitSuperGetElem(PropertyByValue* elem, diff --git a/js/src/frontend/BytecodeSection.cpp b/js/src/frontend/BytecodeSection.cpp index 59db8cdc9ffb..199e1fd01685 100644 --- a/js/src/frontend/BytecodeSection.cpp +++ b/js/src/frontend/BytecodeSection.cpp @@ -58,12 +58,8 @@ bool js::frontend::EmitScriptThingsVector(JSContext* cx, mozilla::Span& 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) diff --git a/js/src/frontend/BytecodeSection.h b/js/src/frontend/BytecodeSection.h index 5108637e2143..29899a3f286b 100644 --- a/js/src/frontend/BytecodeSection.h +++ b/js/src/frontend/BytecodeSection.h @@ -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))); } diff --git a/js/src/frontend/CallOrNewEmitter.cpp b/js/src/frontend/CallOrNewEmitter.cpp index 669df69c5ae7..c0241efb91a4 100644 --- a/js/src/frontend/CallOrNewEmitter.cpp +++ b/js/src/frontend/CallOrNewEmitter.cpp @@ -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 name) { MOZ_ASSERT(state_ == State::Start); NameOpEmitter noe( diff --git a/js/src/frontend/CallOrNewEmitter.h b/js/src/frontend/CallOrNewEmitter.h index 5528e0ae1c84..0ca61882d5d5 100644 --- a/js/src/frontend/CallOrNewEmitter.h +++ b/js/src/frontend/CallOrNewEmitter.h @@ -290,7 +290,7 @@ class MOZ_STACK_CLASS CallOrNewEmitter { } public: - MOZ_MUST_USE bool emitNameCallee(const ParserAtom* name); + MOZ_MUST_USE bool emitNameCallee(Handle name); MOZ_MUST_USE PropOpEmitter& prepareForPropCallee(bool isSuperProp); MOZ_MUST_USE ElemOpEmitter& prepareForElemCallee(bool isSuperElem, bool isPrivateElem); diff --git a/js/src/frontend/CompilationInfo.h b/js/src/frontend/CompilationInfo.h index 91000fe833b6..3d433f2df7d4 100644 --- a/js/src/frontend/CompilationInfo.h +++ b/js/src/frontend/CompilationInfo.h @@ -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; diff --git a/js/src/frontend/EitherParser.h b/js/src/frontend/EitherParser.h index 3528410ba6b9..395bb0ab9d2c 100644 --- a/js/src/frontend/EitherParser.h +++ b/js/src/frontend/EitherParser.h @@ -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 */ diff --git a/js/src/frontend/EmitterScope.cpp b/js/src/frontend/EmitterScope.cpp index 9802599ffd21..820021a3d209 100644 --- a/js/src/frontend/EmitterScope.cpp +++ b/js/src/frontend/EmitterScope.cpp @@ -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 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 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 loc; uint8_t hops = hasEnvironment() ? 1 : 0; DebugOnly 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 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,8 +534,8 @@ bool EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox) { return false; } - ParserBindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT, - /* isNamedLambda = */ true); + BindingIter bi(*funbox->namedLambdaBindings(), LOCALNO_LIMIT, + /* isNamedLambda = */ true); MOZ_ASSERT(bi.kind() == BindingKind::NamedLambdaCallee); // The lambda name, if not closed over, is accessed via JSOp::Callee and @@ -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 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 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 loc = lookupInCache(bce, name)) { return *loc; } return searchAndCache(bce, name); } -Maybe EmitterScope::locationBoundInScope(const ParserAtom* name, +Maybe 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. diff --git a/js/src/frontend/EmitterScope.h b/js/src/frontend/EmitterScope.h index 44c0ea6ab24c..b3f8d13eddc0 100644 --- a/js/src/frontend/EmitterScope.h +++ b/js/src/frontend/EmitterScope.h @@ -66,27 +66,27 @@ class EmitterScope : public Nestable { 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 lookupInCache(BytecodeEmitter* bce, - const ParserAtom* name); + JSAtom* name); EmitterScope* enclosing(BytecodeEmitter** bce) const; mozilla::Maybe 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 { void dump(BytecodeEmitter* bce); MOZ_MUST_USE bool enterLexical(BytecodeEmitter* bce, ScopeKind kind, - ParserLexicalScopeData* bindings); + Handle 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 { return Nestable::enclosing(); } - NameLocation lookup(BytecodeEmitter* bce, const ParserAtom* name); + NameLocation lookup(BytecodeEmitter* bce, JSAtom* name); - mozilla::Maybe locationBoundInScope(const ParserAtom* name, + mozilla::Maybe locationBoundInScope(JSAtom* name, EmitterScope* target); }; diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index c6669d408662..cde7fceb6925 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -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().atom()->toNumber(info.cx(), &d)) { + if (!StringToNumber(info.cx(), pn->as().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().toAtom(info.compilationInfo); + JSAtom* atom = pn->as().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()) { - 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().atom(); + JSAtom* atom = key->as().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(); @@ -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 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().atom(); - if (!accum.append(atom)) { - return false; - } + combination = (*current)->as().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().atom(); - if (!accum.append(nextAtom)) { + // Add this string to the combination and remove the node. + tmp = (*next)->as().atom(); + combination = ConcatStrings(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().setAtom(combination); + (*current)->as().setAtom(&combination->asAtom()); // If we're out of nodes, we're done. if (!*next) { diff --git a/js/src/frontend/Frontend2.cpp b/js/src/frontend/Frontend2.cpp index dcd655ee6b7f..922f4601fcb0 100644 --- a/js/src/frontend/Frontend2.cpp +++ b/js/src/frontend/Frontend2.cpp @@ -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/UniquePtr.h" // js::UniquePtr -#include "js/Utility.h" // JS::UniqueTwoByteChars, StringBufferArena -#include "vm/JSScript.h" // JSScript -#include "vm/ScopeKind.h" // ScopeKind +#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& allAtoms) { + JS::MutableHandleVector 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( - 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& from, - Vector& allAtoms, - ParserBindingName* to) { + JS::HandleVector 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>& from, - Vector& allAtoms, - ParserBindingName* to) { + JS::HandleVector 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>& from, COption& 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>& 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& allAtoms, + JS::HandleVector 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 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 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 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 data( + cx, NewEmptyFunctionScopeData(cx, alloc, numBindings)); if (!data) { return false; } @@ -343,7 +343,7 @@ UniquePtr ConvertImmutableScriptData( // used by a script into ScriptThingsVector. bool ConvertGCThings(JSContext* cx, const SmooshResult& result, const SmooshScriptStencil& smooshStencil, - Vector& allAtoms, + JS::HandleVector allAtoms, MutableHandle 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& allAtoms, + JS::HandleVector allAtoms, CompilationInfo& compilationInfo, MutableHandle stencil) { using ImmutableFlags = js::ImmutableScriptFlagsEnum; @@ -539,8 +540,8 @@ bool Smoosh::compileGlobalScriptToStencil(CompilationInfo& compilationInfo, *unimplemented = false; - Vector allAtoms(cx); - if (!ConvertAtoms(cx, result, compilationInfo, allAtoms)) { + JS::RootedVector allAtoms(cx); + if (!ConvertAtoms(cx, result, compilationInfo, &allAtoms)) { return false; } diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 1aea384ba8a3..d7a25748efd3 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -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 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_(ParseNodeKind::Name, name, pos); } @@ -153,12 +149,11 @@ class FullParseHandler { return new_(ParseNodeKind::ComputedName, pos, expr); } - NameNodeType newObjectLiteralPropertyName(const ParserAtom* atom, - const TokenPos& pos) { + NameNodeType newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) { return new_(ParseNodeKind::ObjectPropertyName, atom, pos); } - NameNodeType newPrivateName(const ParserAtom* atom, const TokenPos& pos) { + NameNodeType newPrivateName(JSAtom* atom, const TokenPos& pos) { return new_(ParseNodeKind::PrivateName, atom, pos); } @@ -177,12 +172,11 @@ class FullParseHandler { return new_(cond, pos); } - NameNodeType newStringLiteral(const ParserAtom* atom, const TokenPos& pos) { + NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) { return new_(ParseNodeKind::StringExpr, atom, pos); } - NameNodeType newTemplateStringLiteral(const ParserAtom* atom, - const TokenPos& pos) { + NameNodeType newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) { return new_(ParseNodeKind::TemplateStringExpr, atom, pos); } @@ -732,12 +726,12 @@ class FullParseHandler { return new_(expr, body, begin); } - ContinueStatementType newContinueStatement(const ParserName* label, + ContinueStatementType newContinueStatement(PropertyName* label, const TokenPos& pos) { return new_(label, pos); } - BreakStatementType newBreakStatement(const ParserName* label, + BreakStatementType newBreakStatement(PropertyName* label, const TokenPos& pos) { return new_(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_(label, stmt, begin); } @@ -777,7 +771,7 @@ class FullParseHandler { return new_(pos); } - NameNodeType newPropertyName(const ParserName* name, const TokenPos& pos) { + NameNodeType newPropertyName(PropertyName* name, const TokenPos& pos) { return new_(ParseNodeKind::PropertyNameExpr, name, pos); } @@ -869,8 +863,7 @@ class FullParseHandler { return new_(pos); } - LexicalScopeNodeType newLexicalScope(ParserLexicalScopeData* bindings, - Node body, + LexicalScopeNodeType newLexicalScope(LexicalScope::Data* bindings, Node body, ScopeKind kind = ScopeKind::Lexical) { return new_(bindings, body, kind); } @@ -1061,14 +1054,14 @@ class FullParseHandler { return false; } - const ParserName* maybeDottedProperty(Node pn) { - return pn->is() ? pn->as().name() + PropertyName* maybeDottedProperty(Node pn) { + return pn->is() ? &pn->as().name() : nullptr; } - const ParserAtom* isStringExprStatement(Node pn, TokenPos* pos) { + JSAtom* isStringExprStatement(Node pn, TokenPos* pos) { if (pn->is()) { UnaryNode* unary = &pn->as(); - if (const ParserAtom* atom = unary->isStringExprStatement()) { + if (JSAtom* atom = unary->isStringExprStatement()) { *pos = unary->kid()->pn_pos; return atom; } diff --git a/js/src/frontend/FunctionEmitter.cpp b/js/src/frontend/FunctionEmitter.cpp index 3b7abb34f46a..53af48e3e9a0 100644 --- a/js/src/frontend/FunctionEmitter.cpp +++ b/js/src/frontend/FunctionEmitter.cpp @@ -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 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 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 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 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 paramName) { // [stack] ARG NameLocation paramLoc = diff --git a/js/src/frontend/FunctionEmitter.h b/js/src/frontend/FunctionEmitter.h index 91de909931fb..d52e3f9e481c 100644 --- a/js/src/frontend/FunctionEmitter.h +++ b/js/src/frontend/FunctionEmitter.h @@ -72,7 +72,7 @@ class MOZ_STACK_CLASS FunctionEmitter { FunctionBox* funbox_; // Function's explicit name. - const ParserAtom* name_; + JS::Rooted 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 paramName); MOZ_MUST_USE bool prepareForDefault(); - MOZ_MUST_USE bool emitDefaultEnd(const ParserAtom* paramName); + MOZ_MUST_USE bool emitDefaultEnd(JS::Handle 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 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 paramName); }; } /* namespace frontend */ diff --git a/js/src/frontend/LabelEmitter.cpp b/js/src/frontend/LabelEmitter.cpp index 23f780579eb7..7bf251b508c3 100644 --- a/js/src/frontend/LabelEmitter.cpp +++ b/js/src/frontend/LabelEmitter.cpp @@ -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()); diff --git a/js/src/frontend/LabelEmitter.h b/js/src/frontend/LabelEmitter.h index 0fc64a28af61..be57f6c006b0 100644 --- a/js/src/frontend/LabelEmitter.h +++ b/js/src/frontend/LabelEmitter.h @@ -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(); }; diff --git a/js/src/frontend/LexicalScopeEmitter.cpp b/js/src/frontend/LexicalScopeEmitter.cpp index fc342d737ef1..073e9ff1e7bd 100644 --- a/js/src/frontend/LexicalScopeEmitter.cpp +++ b/js/src/frontend/LexicalScopeEmitter.cpp @@ -14,7 +14,7 @@ using namespace js::frontend; LexicalScopeEmitter::LexicalScopeEmitter(BytecodeEmitter* bce) : bce_(bce) {} bool LexicalScopeEmitter::emitScope(ScopeKind kind, - ParserLexicalScopeData* bindings) { + JS::Handle bindings) { MOZ_ASSERT(state_ == State::Start); MOZ_ASSERT(bindings); diff --git a/js/src/frontend/LexicalScopeEmitter.h b/js/src/frontend/LexicalScopeEmitter.h index 2629e714e956..8792e893912e 100644 --- a/js/src/frontend/LexicalScopeEmitter.h +++ b/js/src/frontend/LexicalScopeEmitter.h @@ -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 bindings); MOZ_MUST_USE bool emitEmptyScope(); MOZ_MUST_USE bool emitEnd(); diff --git a/js/src/frontend/ModuleSharedContext.h b/js/src/frontend/ModuleSharedContext.h index 892ac267f2bf..a3ceb34a67e0 100644 --- a/js/src/frontend/ModuleSharedContext.h +++ b/js/src/frontend/ModuleSharedContext.h @@ -23,7 +23,7 @@ namespace frontend { class MOZ_STACK_CLASS ModuleSharedContext : public SharedContext { public: - ParserModuleScopeData* bindings; + JS::Rooted bindings; ModuleBuilder& builder; ModuleSharedContext(JSContext* cx, CompilationInfo& compilationInfo, diff --git a/js/src/frontend/NameAnalysisTypes.h b/js/src/frontend/NameAnalysisTypes.h index 56f47a62dc0a..72a4716766a4 100644 --- a/js/src/frontend/NameAnalysisTypes.h +++ b/js/src/frontend/NameAnalysisTypes.h @@ -9,7 +9,6 @@ #include -#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; +using AtomVector = Vector; class FunctionBox; // FunctionBoxes stored in this type are required to be rooted diff --git a/js/src/frontend/NameCollections.h b/js/src/frontend/NameCollections.h index 9d4909467a43..939f7bcecc2f 100644 --- a/js/src/frontend/NameCollections.h +++ b/js/src/frontend/NameCollections.h @@ -134,7 +134,7 @@ struct RecyclableAtomMapValueWrapper { const Wrapped* operator->() const { return &wrapped; } }; -struct NameMapHasher : public DefaultHasher { +struct NameMapHasher : public DefaultHasher { 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 { template using RecyclableNameMap = - InlineMap, 24, + InlineMap, 24, NameMapHasher, SystemAllocPolicy>; using DeclaredNameMap = RecyclableNameMap; diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 0b88798f2a5c..974b7faaa8c3 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -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 { 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 { * 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 { * 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 { 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 { 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 { 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 { } /* 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); } diff --git a/js/src/frontend/NameFunctions.h b/js/src/frontend/NameFunctions.h index 662073f52581..824843303514 100644 --- a/js/src/frontend/NameFunctions.h +++ b/js/src/frontend/NameFunctions.h @@ -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 */ diff --git a/js/src/frontend/NameOpEmitter.cpp b/js/src/frontend/NameOpEmitter.cpp index 19d4433b8282..acf8421d7e8b 100644 --- a/js/src/frontend/NameOpEmitter.cpp +++ b/js/src/frontend/NameOpEmitter.cpp @@ -17,11 +17,11 @@ using namespace js; using namespace js::frontend; -NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, const ParserAtom* name, +NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, Handle 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 name, const NameLocation& loc, Kind kind) : bce_(bce), kind_(kind), name_(name), loc_(loc) {} diff --git a/js/src/frontend/NameOpEmitter.h b/js/src/frontend/NameOpEmitter.h index 07692b63d264..433eca77c010 100644 --- a/js/src/frontend/NameOpEmitter.h +++ b/js/src/frontend/NameOpEmitter.h @@ -80,7 +80,7 @@ class MOZ_STACK_CLASS NameOpEmitter { bool emittedBindOp_ = false; - const ParserAtom* name_; + Handle 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 name, Kind kind); + NameOpEmitter(BytecodeEmitter* bce, Handle name, const NameLocation& loc, Kind kind); private: diff --git a/js/src/frontend/ObjLiteral.cpp b/js/src/frontend/ObjLiteral.cpp index a2e06906977d..c94b452adf8b 100644 --- a/js/src/frontend/ObjLiteral.cpp +++ b/js/src/frontend/ObjLiteral.cpp @@ -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 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 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 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) diff --git a/js/src/frontend/ObjLiteral.h b/js/src/frontend/ObjLiteral.h index 5dc40b041538..03ad8d9a1827 100644 --- a/js/src/frontend/ObjLiteral.h +++ b/js/src/frontend/ObjLiteral.h @@ -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 ObjLiteralAtomVector; +typedef Vector ObjLiteralAtomVector; -JSObject* InterpretObjLiteral(JSContext* cx, - frontend::CompilationInfo& compilationInfo, - const ObjLiteralAtomVector& atoms, +JSObject* InterpretObjLiteral(JSContext* cx, const ObjLiteralAtomVector& atoms, const mozilla::Span 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(); diff --git a/js/src/frontend/ObjectEmitter.cpp b/js/src/frontend/ObjectEmitter.cpp index dc46c3c682aa..12bf2d1624de 100644 --- a/js/src/frontend/ObjectEmitter.cpp +++ b/js/src/frontend/ObjectEmitter.cpp @@ -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 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 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 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 name, + JS::Handle 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 name, + JS::Handle 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()) { diff --git a/js/src/frontend/ObjectEmitter.h b/js/src/frontend/ObjectEmitter.h index c1fd63c673c1..c5e30425acc0 100644 --- a/js/src/frontend/ObjectEmitter.h +++ b/js/src/frontend/ObjectEmitter.h @@ -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 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 name_; + JS::Rooted nameForAnonymousClass_; bool hasNameOnStack_ = false; mozilla::Maybe 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 scopeBindings); + + bool emitBodyScope(JS::Handle 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 name, + JS::Handle nameForAnonymousClass, bool hasNameOnStack); - MOZ_MUST_USE bool emitDerivedClass(const ParserAtom* name, - const ParserAtom* nameForAnonymousClass, + MOZ_MUST_USE bool emitDerivedClass(JS::Handle name, + JS::Handle nameForAnonymousClass, bool hasNameOnStack); // @param needsHomeObject diff --git a/js/src/frontend/ParseContext-inl.h b/js/src/frontend/ParseContext-inl.h index f878749e0565..1e97170cf241 100644 --- a/js/src/frontend/ParseContext-inl.h +++ b/js/src/frontend/ParseContext-inl.h @@ -63,7 +63,7 @@ inline ParseContext::VarScope::VarScope(JSContext* cx, ParseContext* pc, } inline JS::Result -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 -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. diff --git a/js/src/frontend/ParseContext.cpp b/js/src/frontend/ParseContext.cpp index 8b56e5fe470b..a1c152d5b44a 100644 --- a/js/src/frontend/ParseContext.cpp +++ b/js/src/frontend/ParseContext.cpp @@ -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 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 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 redeclaredKind = isVarRedeclaredInInnermostScope( name, DeclarationKind::VarForAnnexBLexicalFunction); @@ -376,7 +377,7 @@ bool ParseContext::annexBAppliesToLexicalFunctionInInnermostScope( } Maybe ParseContext::isVarRedeclaredInInnermostScope( - const ParserName* name, DeclarationKind kind) { + HandlePropertyName name, DeclarationKind kind) { Maybe redeclaredKind; uint32_t unused; MOZ_ALWAYS_TRUE(tryDeclareVarHelper( @@ -384,20 +385,11 @@ Maybe ParseContext::isVarRedeclaredInInnermostScope( return redeclaredKind; } -bool ParseContext::isVarRedeclaredInEval(const ParserName* name, - DeclarationKind kind, - Maybe* out) { - MOZ_ASSERT(out); +Maybe 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* redeclaredKind, uint32_t* prevPos) { @@ -453,7 +442,7 @@ bool ParseContext::tryDeclareVar(const ParserName* name, DeclarationKind kind, } template -bool ParseContext::tryDeclareVarHelper(const ParserName* name, +bool ParseContext::tryDeclareVarHelper(HandlePropertyName name, DeclarationKind kind, uint32_t beginPos, Maybe* 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, diff --git a/js/src/frontend/ParseContext.h b/js/src/frontend/ParseContext.h index 1a250eaac066..7199bc8b384b 100644 --- a/js/src/frontend/ParseContext.h +++ b/js/src/frontend/ParseContext.h @@ -69,13 +69,13 @@ class ParseContext : public Nestable { }; 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 { 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 { 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 { // Return Err(true) if we have encountered at least one loop, // Err(false) otherwise. MOZ_MUST_USE inline JS::Result checkBreakStatement( - const ParserName* label); + PropertyName* label); enum class ContinueStatementError { NotInALoop, LabelNotFound, }; MOZ_MUST_USE inline JS::Result - 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 { bool annexBAppliesToLexicalFunctionInInnermostScope(FunctionBox* funbox); - bool tryDeclareVar(const ParserName* name, DeclarationKind kind, + bool tryDeclareVar(HandlePropertyName name, DeclarationKind kind, uint32_t beginPos, mozilla::Maybe* 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 { private: mozilla::Maybe isVarRedeclaredInInnermostScope( - const ParserName* name, DeclarationKind kind); - - MOZ_MUST_USE bool isVarRedeclaredInEval(const ParserName* name, - DeclarationKind kind, - mozilla::Maybe* out); + HandlePropertyName name, DeclarationKind kind); + mozilla::Maybe isVarRedeclaredInEval(HandlePropertyName name, + DeclarationKind kind); enum DryRunOption { NotDryRun, DryRunInnermostScopeOnly }; template - bool tryDeclareVarHelper(const ParserName* name, DeclarationKind kind, + bool tryDeclareVarHelper(HandlePropertyName name, DeclarationKind kind, uint32_t beginPos, mozilla::Maybe* redeclaredKind, uint32_t* prevPos); diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index b633b066ae21..42f538bd9fd3 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -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("#"); } 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* 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 { diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index a4b0be9662b2..cdf7db68a074 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -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` 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; - -template -using ParserScopeData = typename Scope::template AbstractData; - #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()); } @@ -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().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().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* bindings; + LexicalScope::Data* bindings; ParseNode* body; ScopeKind kind_; public: - LexicalScopeNode(ParserScopeData* 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* scopeBindings() const { + Handle 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::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().atom()->asName(); + PropertyName& name() const { + return *right()->as().atom()->asPropertyName(); } }; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index a25227e771a3..bdd2938650a8 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -88,7 +88,7 @@ using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr; using BindingIter = ParseContext::Scope::BindingIter; using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr; -using ParserBindingNameVector = Vector; +using BindingNameVector = Vector; template static inline void PropagateTransitiveParseFlags(const T* inner, U* outer) { @@ -246,8 +246,8 @@ inline void GeneralParser::setInParametersOfAsyncFunction( template FunctionBox* PerHandlerParser::newFunctionBox( - FunctionNodeType funNode, const ParserAtom* explicitName, - FunctionFlags flags, uint32_t toStringStart, Directives inheritedDirectives, + FunctionNodeType funNode, JSAtom* explicitName, FunctionFlags flags, + uint32_t toStringStart, Directives inheritedDirectives, GeneratorKind generatorKind, FunctionAsyncKind asyncKind, TopLevelFunction isTopLevel) { MOZ_ASSERT(funNode); @@ -398,7 +398,7 @@ typename ParseHandler::ListNodeType GeneralParser::parse() { * Strict mode forbids introducing new definitions for 'eval', 'arguments', * 'let', 'static', 'yield', or for any strict mode reserved word. */ -bool ParserBase::isValidStrictBinding(const ParserName* name) { +bool ParserBase::isValidStrictBinding(PropertyName* name) { TokenKind tt = ReservedWordTokenKind(name); if (tt == TokenKind::Name) { return name != cx_->parserNames().eval && @@ -420,9 +420,9 @@ bool ParserBase::hasValidSimpleStrictParameterNames() { return false; } - for (auto name : pc_->positionalFormalParameterNames()) { + for (auto* name : pc_->positionalFormalParameterNames()) { MOZ_ASSERT(name); - if (!isValidStrictBinding(name->asName())) { + if (!isValidStrictBinding(name->asPropertyName())) { return false; } } @@ -458,9 +458,9 @@ void GeneralParser::reportMissingClosing( template void GeneralParser::reportRedeclaration( - const ParserName* name, DeclarationKind prevKind, TokenPos pos, + HandlePropertyName name, DeclarationKind prevKind, TokenPos pos, uint32_t prevPos) { - UniqueChars bytes = ParserAtomToPrintableString(cx_, name); + UniqueChars bytes = AtomToPrintableString(cx_, name); if (!bytes) { return; } @@ -507,7 +507,7 @@ void GeneralParser::reportRedeclaration( // forbid duplicates.) template bool GeneralParser::notePositionalFormalParameter( - FunctionNodeType funNode, const ParserName* name, uint32_t beginPos, + FunctionNodeType funNode, HandlePropertyName name, uint32_t beginPos, bool disallowDuplicateParams, bool* duplicatedParam) { if (AddDeclaredNamePtr p = pc_->functionScope().lookupDeclaredNameForAdd(name)) { @@ -521,7 +521,7 @@ bool GeneralParser::notePositionalFormalParameter( // In such cases, report will queue up the potential error and return // 'true'. if (pc_->sc()->strict()) { - UniqueChars bytes = ParserAtomToPrintableString(cx_, name); + UniqueChars bytes = AtomToPrintableString(cx_, name); if (!bytes) { return false; } @@ -556,7 +556,7 @@ template bool PerHandlerParser::noteDestructuredPositionalFormalParameter( FunctionNodeType funNode, Node destruct) { // Append an empty name to the positional formals vector to keep track of - // argument slots when making ParserFunctionScopeData. + // argument slots when making FunctionScope::Data. if (!pc_->positionalFormalParameterNames().append(nullptr)) { ReportOutOfMemory(cx_); return false; @@ -567,9 +567,8 @@ bool PerHandlerParser::noteDestructuredPositionalFormalParameter( } template -bool GeneralParser::noteDeclaredName(const ParserName* name, - DeclarationKind kind, - TokenPos pos) { +bool GeneralParser::noteDeclaredName( + HandlePropertyName name, DeclarationKind kind, TokenPos pos) { // The asm.js validator does all its own symbol-table management so, as an // optimization, avoid doing any work here. if (pc_->useAsmOrInsideUseAsm()) { @@ -746,7 +745,7 @@ bool GeneralParser::noteDeclaredName(const ParserName* name, template bool GeneralParser::noteDeclaredPrivateName( - Node nameNode, const ParserName* name, PropertyType propType, + Node nameNode, HandlePropertyName name, PropertyType propType, TokenPos pos) { ParseContext::Scope* scope = pc_->innermostScope(); AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name); @@ -797,7 +796,7 @@ bool GeneralParser::noteDeclaredPrivateName( return true; } -bool ParserBase::noteUsedNameInternal(const ParserName* name, +bool ParserBase::noteUsedNameInternal(HandlePropertyName name, NameVisibility visibility, mozilla::Maybe tokenPosition) { // The asm.js validator does all its own symbol-table management so, as an @@ -837,16 +836,7 @@ bool PerHandlerParser:: // Scopes are nullptr-delimited in the BaseScript closed over bindings // array. while (JSAtom* name = handler_.nextLazyClosedOverBinding()) { - // TODO-Stencil - // After closed-over-bindings are snapshotted in the handler, - // remove this. - auto mbNameId = compilationInfo_.parserAtoms.internJSAtom(cx_, name); - if (mbNameId.isErr()) { - return false; - } - const ParserName* nameId = mbNameId.unwrap()->asName(); - - scope.lookupDeclaredName(nameId)->value()->setClosedOver(); + scope.lookupDeclaredName(name)->value()->setClosedOver(); } return true; } @@ -902,11 +892,11 @@ bool Parser::checkStatementsEOF() { return true; } -template -ParserScopeData* NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, - uint32_t numBindings) { - using Data = ParserScopeData; - size_t allocSize = SizeOfScopeData(numBindings); +template +typename Scope::Data* NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings) { + using Data = typename Scope::Data; + size_t allocSize = SizeOfData(numBindings); auto* bindings = alloc.newWithSize(allocSize, numBindings); if (!bindings) { ReportOutOfMemory(cx); @@ -914,39 +904,37 @@ ParserScopeData* NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, return bindings; } -ParserGlobalScopeData* NewEmptyGlobalScopeData(JSContext* cx, LifoAlloc& alloc, - uint32_t numBindings) { +GlobalScope::Data* NewEmptyGlobalScopeData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings) { return NewEmptyBindingData(cx, alloc, numBindings); } -ParserLexicalScopeData* NewEmptyLexicalScopeData(JSContext* cx, - LifoAlloc& alloc, - uint32_t numBindings) { +LexicalScope::Data* NewEmptyLexicalScopeData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings) { return NewEmptyBindingData(cx, alloc, numBindings); } -ParserFunctionScopeData* NewEmptyFunctionScopeData(JSContext* cx, - LifoAlloc& alloc, - uint32_t numBindings) { +FunctionScope::Data* NewEmptyFunctionScopeData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings) { return NewEmptyBindingData(cx, alloc, numBindings); } namespace detail { template -static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( - Data* data, ParserBindingName* start, ParserBindingName* cursor) { +static MOZ_ALWAYS_INLINE BindingName* InitializeIndexedBindings( + Data* data, BindingName* start, BindingName* cursor) { return cursor; } template -static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( - Data* data, ParserBindingName* start, ParserBindingName* cursor, - UnsignedInteger Data::*field, const ParserBindingNameVector& bindings, +static MOZ_ALWAYS_INLINE BindingName* InitializeIndexedBindings( + Data* data, BindingName* start, BindingName* cursor, + UnsignedInteger Data::*field, const BindingNameVector& bindings, Step&&... step) { data->*field = AssertedCast(PointerRangeSize(start, cursor)); - ParserBindingName* newCursor = + BindingName* newCursor = std::uninitialized_copy(bindings.begin(), bindings.end(), cursor); return InitializeIndexedBindings(data, start, newCursor, @@ -961,20 +949,20 @@ static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings( // First, |firstBindings| are added to |data->trailingNames|. Then any "steps" // present are performed first to last. Each step is 1) a pointer to a member // of |data| to be set to the current number of bindings added, and 2) a vector -// of |ParserBindingName|s to then copy into |data->trailingNames|. (Thus each +// of |BindingName|s to then copy into |data->trailingNames|. (Thus each // |data| member field indicates where the corresponding vector's names start.) template static MOZ_ALWAYS_INLINE void InitializeBindingData( - Data* data, uint32_t count, const ParserBindingNameVector& firstBindings, + Data* data, uint32_t count, const BindingNameVector& firstBindings, Step&&... step) { MOZ_ASSERT(data->length == 0, "data shouldn't be filled yet"); - ParserBindingName* start = data->trailingNames.start(); - ParserBindingName* cursor = std::uninitialized_copy( - firstBindings.begin(), firstBindings.end(), start); + BindingName* start = data->trailingNames.start(); + BindingName* cursor = std::uninitialized_copy(firstBindings.begin(), + firstBindings.end(), start); #ifdef DEBUG - ParserBindingName* end = + BindingName* end = #endif detail::InitializeIndexedBindings(data, start, cursor, std::forward(step)...); @@ -983,13 +971,13 @@ static MOZ_ALWAYS_INLINE void InitializeBindingData( data->length = count; } -Maybe NewGlobalScopeData(JSContext* cx, - ParseContext::Scope& scope, - LifoAlloc& alloc, - ParseContext* pc) { - ParserBindingNameVector vars(cx); - ParserBindingNameVector lets(cx); - ParserBindingNameVector consts(cx); +Maybe NewGlobalScopeData(JSContext* cx, + ParseContext::Scope& scope, + LifoAlloc& alloc, + ParseContext* pc) { + BindingNameVector vars(cx); + BindingNameVector lets(cx); + BindingNameVector consts(cx); bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver(); for (BindingIter bi = scope.bindings(pc); bi; bi++) { @@ -999,22 +987,21 @@ Maybe NewGlobalScopeData(JSContext* cx, case BindingKind::Var: { bool isTopLevelFunction = bi.declarationKind() == DeclarationKind::BodyLevelFunction; - - ParserBindingName binding(bi.name(), closedOver, isTopLevelFunction); + BindingName binding(bi.name(), closedOver, isTopLevelFunction); if (!vars.append(binding)) { return Nothing(); } break; } case BindingKind::Let: { - ParserBindingName binding(bi.name(), closedOver); + BindingName binding(bi.name(), closedOver); if (!lets.append(binding)) { return Nothing(); } break; } case BindingKind::Const: { - ParserBindingName binding(bi.name(), closedOver); + BindingName binding(bi.name(), closedOver); if (!consts.append(binding)) { return Nothing(); } @@ -1025,7 +1012,7 @@ Maybe NewGlobalScopeData(JSContext* cx, } } - ParserGlobalScopeData* bindings = nullptr; + GlobalScope::Data* bindings = nullptr; uint32_t numBindings = vars.length() + lets.length() + consts.length(); if (numBindings > 0) { @@ -1036,33 +1023,32 @@ Maybe NewGlobalScopeData(JSContext* cx, // The ordering here is important. See comments in GlobalScope. InitializeBindingData(bindings, numBindings, vars, - &ParserGlobalScopeData::letStart, lets, - &ParserGlobalScopeData::constStart, consts); + &GlobalScope::Data::letStart, lets, + &GlobalScope::Data::constStart, consts); } return Some(bindings); } -Maybe ParserBase::newGlobalScopeData( +Maybe ParserBase::newGlobalScopeData( ParseContext::Scope& scope) { return NewGlobalScopeData(cx_, scope, alloc_, pc_); } -Maybe NewModuleScopeData(JSContext* cx, - ParseContext::Scope& scope, - LifoAlloc& alloc, - ParseContext* pc) { - ParserBindingNameVector imports(cx); - ParserBindingNameVector vars(cx); - ParserBindingNameVector lets(cx); - ParserBindingNameVector consts(cx); +Maybe NewModuleScopeData(JSContext* cx, + ParseContext::Scope& scope, + LifoAlloc& alloc, + ParseContext* pc) { + BindingNameVector imports(cx); + BindingNameVector vars(cx); + BindingNameVector lets(cx); + BindingNameVector consts(cx); bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver(); for (BindingIter bi = scope.bindings(pc); bi; bi++) { // Imports are indirect bindings and must not be given known slots. - ParserBindingName binding(bi.name(), - (allBindingsClosedOver || bi.closedOver()) && - bi.kind() != BindingKind::Import); + BindingName binding(bi.name(), (allBindingsClosedOver || bi.closedOver()) && + bi.kind() != BindingKind::Import); switch (bi.kind()) { case BindingKind::Import: if (!imports.append(binding)) { @@ -1089,7 +1075,7 @@ Maybe NewModuleScopeData(JSContext* cx, } } - ParserModuleScopeData* bindings = nullptr; + ModuleScope::Data* bindings = nullptr; uint32_t numBindings = imports.length() + vars.length() + lets.length() + consts.length(); @@ -1101,24 +1087,23 @@ Maybe NewModuleScopeData(JSContext* cx, // The ordering here is important. See comments in ModuleScope. InitializeBindingData(bindings, numBindings, imports, - &ParserModuleScopeData::varStart, vars, - &ParserModuleScopeData::letStart, lets, - &ParserModuleScopeData::constStart, consts); + &ModuleScope::Data::varStart, vars, + &ModuleScope::Data::letStart, lets, + &ModuleScope::Data::constStart, consts); } return Some(bindings); } -Maybe ParserBase::newModuleScopeData( +Maybe ParserBase::newModuleScopeData( ParseContext::Scope& scope) { return NewModuleScopeData(cx_, scope, alloc_, pc_); } -Maybe NewEvalScopeData(JSContext* cx, - ParseContext::Scope& scope, - LifoAlloc& alloc, - ParseContext* pc) { - ParserBindingNameVector vars(cx); +Maybe NewEvalScopeData(JSContext* cx, + ParseContext::Scope& scope, + LifoAlloc& alloc, ParseContext* pc) { + BindingNameVector vars(cx); for (BindingIter bi = scope.bindings(pc); bi; bi++) { // Eval scopes only contain 'var' bindings. Make all bindings aliased @@ -1126,14 +1111,13 @@ Maybe NewEvalScopeData(JSContext* cx, MOZ_ASSERT(bi.kind() == BindingKind::Var); bool isTopLevelFunction = bi.declarationKind() == DeclarationKind::BodyLevelFunction; - - ParserBindingName binding(bi.name(), true, isTopLevelFunction); + BindingName binding(bi.name(), true, isTopLevelFunction); if (!vars.append(binding)) { return Nothing(); } } - ParserEvalScopeData* bindings = nullptr; + EvalScope::Data* bindings = nullptr; uint32_t numBindings = vars.length(); if (numBindings > 0) { @@ -1148,19 +1132,19 @@ Maybe NewEvalScopeData(JSContext* cx, return Some(bindings); } -Maybe ParserBase::newEvalScopeData( +Maybe ParserBase::newEvalScopeData( ParseContext::Scope& scope) { return NewEvalScopeData(cx_, scope, alloc_, pc_); } -Maybe NewFunctionScopeData(JSContext* cx, - ParseContext::Scope& scope, - bool hasParameterExprs, - LifoAlloc& alloc, - ParseContext* pc) { - ParserBindingNameVector positionalFormals(cx); - ParserBindingNameVector formals(cx); - ParserBindingNameVector vars(cx); +Maybe NewFunctionScopeData(JSContext* cx, + ParseContext::Scope& scope, + bool hasParameterExprs, + LifoAlloc& alloc, + ParseContext* pc) { + BindingNameVector positionalFormals(cx); + BindingNameVector formals(cx); + BindingNameVector vars(cx); bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver(); bool hasDuplicateParams = pc->functionBox()->hasDuplicateParameters; @@ -1168,9 +1152,9 @@ Maybe NewFunctionScopeData(JSContext* cx, // Positional parameter names must be added in order of appearance as they are // referenced using argument slots. for (size_t i = 0; i < pc->positionalFormalParameterNames().length(); i++) { - const ParserAtom* name = pc->positionalFormalParameterNames()[i]; + JSAtom* name = pc->positionalFormalParameterNames()[i]; - ParserBindingName bindName; + BindingName bindName; if (name) { DeclaredNamePtr p = scope.lookupDeclaredName(name); @@ -1193,7 +1177,7 @@ Maybe NewFunctionScopeData(JSContext* cx, } } - bindName = ParserBindingName(name, closedOver); + bindName = BindingName(name, closedOver); } if (!positionalFormals.append(bindName)) { @@ -1202,8 +1186,7 @@ Maybe NewFunctionScopeData(JSContext* cx, } for (BindingIter bi = scope.bindings(pc); bi; bi++) { - ParserBindingName binding(bi.name(), - allBindingsClosedOver || bi.closedOver()); + BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver()); switch (bi.kind()) { case BindingKind::FormalParameter: // Positional parameter names are already handled above. @@ -1228,7 +1211,7 @@ Maybe NewFunctionScopeData(JSContext* cx, } } - ParserFunctionScopeData* bindings = nullptr; + FunctionScope::Data* bindings = nullptr; uint32_t numBindings = positionalFormals.length() + formals.length() + vars.length(); @@ -1240,8 +1223,8 @@ Maybe NewFunctionScopeData(JSContext* cx, // The ordering here is important. See comments in FunctionScope. InitializeBindingData(bindings, numBindings, positionalFormals, - &ParserFunctionScopeData::nonPositionalFormalStart, - formals, &ParserFunctionScopeData::varStart, vars); + &FunctionScope::Data::nonPositionalFormalStart, + formals, &FunctionScope::Data::varStart, vars); } return Some(bindings); @@ -1270,34 +1253,33 @@ bool FunctionScopeHasClosedOverBindings(ParseContext* pc) { return false; } -Maybe ParserBase::newFunctionScopeData( +Maybe ParserBase::newFunctionScopeData( ParseContext::Scope& scope, bool hasParameterExprs) { return NewFunctionScopeData(cx_, scope, hasParameterExprs, alloc_, pc_); } -ParserVarScopeData* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc, - uint32_t numBindings) { +VarScope::Data* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings) { return NewEmptyBindingData(cx, alloc, numBindings); } -Maybe NewVarScopeData(JSContext* cx, - ParseContext::Scope& scope, - LifoAlloc& alloc, ParseContext* pc) { - ParserBindingNameVector vars(cx); +Maybe NewVarScopeData(JSContext* cx, + ParseContext::Scope& scope, + LifoAlloc& alloc, ParseContext* pc) { + BindingNameVector vars(cx); bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver(); for (BindingIter bi = scope.bindings(pc); bi; bi++) { if (bi.kind() == BindingKind::Var) { - ParserBindingName binding(bi.name(), - allBindingsClosedOver || bi.closedOver()); + BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver()); if (!vars.append(binding)) { return Nothing(); } } } - ParserVarScopeData* bindings = nullptr; + VarScope::Data* bindings = nullptr; uint32_t numBindings = vars.length(); if (numBindings > 0) { @@ -1324,23 +1306,21 @@ static bool VarScopeHasBindings(ParseContext* pc) { return false; } -Maybe ParserBase::newVarScopeData( - ParseContext::Scope& scope) { +Maybe ParserBase::newVarScopeData(ParseContext::Scope& scope) { return NewVarScopeData(cx_, scope, alloc_, pc_); } -Maybe NewLexicalScopeData(JSContext* cx, - ParseContext::Scope& scope, - LifoAlloc& alloc, - ParseContext* pc) { - ParserBindingNameVector lets(cx); - ParserBindingNameVector consts(cx); +Maybe NewLexicalScopeData(JSContext* cx, + ParseContext::Scope& scope, + LifoAlloc& alloc, + ParseContext* pc) { + BindingNameVector lets(cx); + BindingNameVector consts(cx); bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver(); for (BindingIter bi = scope.bindings(pc); bi; bi++) { - ParserBindingName binding(bi.name(), - allBindingsClosedOver || bi.closedOver()); + BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver()); switch (bi.kind()) { case BindingKind::Let: if (!lets.append(binding)) { @@ -1357,7 +1337,7 @@ Maybe NewLexicalScopeData(JSContext* cx, } } - ParserLexicalScopeData* bindings = nullptr; + LexicalScope::Data* bindings = nullptr; uint32_t numBindings = lets.length() + consts.length(); if (numBindings > 0) { @@ -1368,7 +1348,7 @@ Maybe NewLexicalScopeData(JSContext* cx, // The ordering here is important. See comments in LexicalScope. InitializeBindingData(bindings, numBindings, lets, - &ParserLexicalScopeData::constStart, consts); + &LexicalScope::Data::constStart, consts); } return Some(bindings); @@ -1398,7 +1378,7 @@ bool LexicalScopeHasClosedOverBindings(ParseContext* pc, return false; } -Maybe ParserBase::newLexicalScopeData( +Maybe ParserBase::newLexicalScopeData( ParseContext::Scope& scope) { return NewLexicalScopeData(cx_, scope, alloc_, pc_); } @@ -1421,7 +1401,7 @@ LexicalScopeNode* PerHandlerParser::finishLexicalScope( return nullptr; } - Maybe bindings = newLexicalScopeData(scope); + Maybe bindings = newLexicalScopeData(scope); if (!bindings) { return nullptr; } @@ -1455,7 +1435,7 @@ bool PerHandlerParser::checkForUndefinedPrivateFields( if (!evalSc) { // The unbound private names are sorted, so just grab the first one. UnboundPrivateName minimum = unboundPrivateNames[0]; - UniqueChars str = ParserAtomToPrintableString(cx_, minimum.atom); + UniqueChars str = AtomToPrintableString(cx_, minimum.atom); if (!str) { return false; } @@ -1478,7 +1458,7 @@ bool PerHandlerParser::checkForUndefinedPrivateFields( // Look for a matching binding. for (js::BindingIter bi(si.scope()); bi; bi++) { - if (unboundName.atom->equalsJSAtom(bi.name())) { + if (bi.name() == unboundName.atom) { // Awesome. We found it, we're done here! return true; } @@ -1486,7 +1466,7 @@ bool PerHandlerParser::checkForUndefinedPrivateFields( } // Didn't find a matching binding, so issue an error. - UniqueChars str = ParserAtomToPrintableString(cx, unboundName.atom); + UniqueChars str = AtomToPrintableString(cx, unboundName.atom); if (!str) { return false; } @@ -1598,7 +1578,7 @@ LexicalScopeNode* Parser::evalBody( return nullptr; } - Maybe bindings = newEvalScopeData(pc_->varScope()); + Maybe bindings = newEvalScopeData(pc_->varScope()); if (!bindings) { return nullptr; } @@ -1658,7 +1638,7 @@ ListNode* Parser::globalBody( return nullptr; } - Maybe bindings = newGlobalScopeData(pc_->varScope()); + Maybe bindings = newGlobalScopeData(pc_->varScope()); if (!bindings) { return nullptr; } @@ -1716,12 +1696,12 @@ ModuleNode* Parser::moduleBody( StencilModuleMetadata& moduleMetadata = this->compilationInfo_.moduleMetadata.get(); for (auto entry : moduleMetadata.localExportEntries) { - const ParserAtom* nameId = entry.localName; - MOZ_ASSERT(nameId); + JSAtom* name = entry.localName; + MOZ_ASSERT(name); - DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(nameId); + DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(name); if (!p) { - UniqueChars str = ParserAtomToPrintableString(cx_, nameId); + UniqueChars str = AtomToPrintableString(cx_, name); if (!str) { return null(); } @@ -1735,12 +1715,12 @@ ModuleNode* Parser::moduleBody( // Reserve an environment slot for a "*namespace*" psuedo-binding and mark as // closed-over. We do not know until module linking if this will be used. - if (!noteDeclaredName(cx_->parserNames().starNamespaceStar, - DeclarationKind::Const, pos())) { + if (!noteDeclaredName(cx_->names().starNamespaceStar, DeclarationKind::Const, + pos())) { return nullptr; } modulepc.varScope() - .lookupDeclaredName(cx_->parserNames().starNamespaceStar) + .lookupDeclaredName(cx_->names().starNamespaceStar) ->value() ->setClosedOver(); @@ -1771,8 +1751,7 @@ ModuleNode* Parser::moduleBody( return null(); } - Maybe bindings = - newModuleScopeData(modulepc.varScope()); + Maybe bindings = newModuleScopeData(modulepc.varScope()); if (!bindings) { return nullptr; } @@ -1790,7 +1769,7 @@ SyntaxParseHandler::ModuleNodeType Parser::moduleBody( template typename ParseHandler::NameNodeType -PerHandlerParser::newInternalDotName(const ParserName* name) { +PerHandlerParser::newInternalDotName(HandlePropertyName name) { NameNodeType nameNode = newName(name); if (!nameNode) { return null(); @@ -1872,11 +1851,11 @@ bool PerHandlerParser::finishFunction( bool hasParameterExprs = funbox->hasParameterExprs; if (hasParameterExprs) { - Maybe bindings = newVarScopeData(pc_->varScope()); + Maybe bindings = newVarScopeData(pc_->varScope()); if (!bindings) { return false; } - funbox->setExtraVarScopeBindings(*bindings); + funbox->extraVarScopeBindings().set(*bindings); MOZ_ASSERT(bool(*bindings) == VarScopeHasBindings(pc_)); MOZ_ASSERT_IF(!funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings(), @@ -1884,21 +1863,21 @@ bool PerHandlerParser::finishFunction( } { - Maybe bindings = + Maybe bindings = newFunctionScopeData(pc_->functionScope(), hasParameterExprs); if (!bindings) { return false; } - funbox->setFunctionScopeBindings(*bindings); + funbox->functionScopeBindings().set(*bindings); } if (funbox->isNamedLambda() && !isStandaloneFunction) { - Maybe bindings = + Maybe bindings = newLexicalScopeData(pc_->namedLambdaScope()); if (!bindings) { return false; } - funbox->setNamedLambdaBindings(*bindings); + funbox->namedLambdaBindings().set(*bindings); } funbox->finishScriptFlags(); @@ -1929,9 +1908,9 @@ bool PerHandlerParser::finishFunction( // Elide nullptr sentinels from end of binding list. These are inserted for // each scope regardless of if any bindings are actually closed over. { - AtomVector& closedOver = pc_->closedOverBindingsForLazy(); - while (!closedOver.empty() && !closedOver.back()) { - closedOver.popBack(); + AtomVector& COB = pc_->closedOverBindingsForLazy(); + while (!COB.empty() && (COB.back() == nullptr)) { + COB.popBack(); } } @@ -2077,7 +2056,7 @@ FunctionNode* Parser::standaloneFunction( } // Skip function name, if present. - const ParserAtom* explicitName = nullptr; + RootedAtom explicitName(cx_); if (TokenKindIsPossibleIdentifierName(tt)) { explicitName = anyChars.currentName(); } else { @@ -2334,9 +2313,9 @@ bool ParserBase::leaveInnerFunction(ParseContext* outerpc) { return true; } -const ParserAtom* ParserBase::prefixAccessorName(PropertyType propType, - const ParserAtom* propAtom) { - const ParserAtom* prefix = nullptr; +JSAtom* ParserBase::prefixAccessorName(PropertyType propType, + HandleAtom propAtom) { + RootedAtom prefix(cx_); if (propType == PropertyType::Setter) { prefix = cx_->parserNames().setPrefix; } else { @@ -2344,10 +2323,13 @@ const ParserAtom* ParserBase::prefixAccessorName(PropertyType propType, prefix = cx_->parserNames().getPrefix; } - const ParserAtom* atoms[2] = {prefix, propAtom}; - auto atomsRange = mozilla::Range(atoms, 2); - return compilationInfo_.parserAtoms.concatAtoms(cx_, atomsRange) - .unwrapOr(nullptr); + RootedString str( + cx_, ConcatStrings(cx_, prefix, propAtom, js::gc::TenuredHeap)); + if (!str) { + return nullptr; + } + + return AtomizeString(cx_, str); } template @@ -2545,7 +2527,7 @@ bool GeneralParser::functionArguments( setFunctionStartAtCurrentToken(funbox); } - const ParserName* name = bindingIdentifier(yieldHandling); + RootedPropertyName name(cx_, bindingIdentifier(yieldHandling)); if (!name) { return false; } @@ -2681,19 +2663,8 @@ bool Parser::skipLazyInnerFunction( // so we can skip over them after accounting for their free variables. RootedFunction fun(cx_, handler_.nextLazyInnerFunction()); - - // TODO-Stencil: Consider for snapshotting. - const ParserAtom* displayAtom = nullptr; - if (fun->displayAtom()) { - displayAtom = - this->compilationInfo_.lowerJSAtomToParserAtom(fun->displayAtom()); - if (!displayAtom) { - return false; - } - } - FunctionBox* funbox = - newFunctionBox(funNode, displayAtom, fun->flags(), toStringStart, + newFunctionBox(funNode, fun->displayAtom(), fun->flags(), toStringStart, Directives(/* strict = */ false), fun->generatorKind(), fun->asyncKind(), TopLevelFunction::No); if (!funbox) { @@ -2828,9 +2799,9 @@ template typename ParseHandler::FunctionNodeType GeneralParser::functionDefinition( FunctionNodeType funNode, uint32_t toStringStart, InHandling inHandling, - YieldHandling yieldHandling, const ParserAtom* funName, - FunctionSyntaxKind kind, GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, bool tryAnnexB /* = false */) { + YieldHandling yieldHandling, HandleAtom funName, FunctionSyntaxKind kind, + GeneratorKind generatorKind, FunctionAsyncKind asyncKind, + bool tryAnnexB /* = false */) { MOZ_ASSERT_IF(kind == FunctionSyntaxKind::Statement, funName); // If we see any inner function, note it on our current context. The bytecode @@ -2921,7 +2892,7 @@ bool Parser::advancePastSyntaxParsedFunction( template bool Parser::trySyntaxParseInnerFunction( - FunctionNode** funNode, const ParserAtom* explicitName, FunctionFlags flags, + FunctionNode** funNode, HandleAtom explicitName, FunctionFlags flags, uint32_t toStringStart, InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, Directives inheritedDirectives, @@ -3024,11 +2995,11 @@ bool Parser::trySyntaxParseInnerFunction( template bool Parser::trySyntaxParseInnerFunction( - FunctionNodeType* funNode, const ParserAtom* explicitName, - FunctionFlags flags, uint32_t toStringStart, InHandling inHandling, - YieldHandling yieldHandling, FunctionSyntaxKind kind, - GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, - Directives inheritedDirectives, Directives* newDirectives) { + 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) { // This is already a syntax parser, so just parse the inner function. FunctionNodeType innerFunc = innerFunction(*funNode, pc_, explicitName, flags, toStringStart, @@ -3045,11 +3016,11 @@ bool Parser::trySyntaxParseInnerFunction( template inline bool GeneralParser::trySyntaxParseInnerFunction( - FunctionNodeType* funNode, const ParserAtom* explicitName, - FunctionFlags flags, uint32_t toStringStart, InHandling inHandling, - YieldHandling yieldHandling, FunctionSyntaxKind kind, - GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, - Directives inheritedDirectives, Directives* newDirectives) { + 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) { return asFinalParser()->trySyntaxParseInnerFunction( funNode, explicitName, flags, toStringStart, inHandling, yieldHandling, kind, generatorKind, asyncKind, tryAnnexB, inheritedDirectives, @@ -3088,9 +3059,9 @@ GeneralParser::innerFunctionForFunctionBox( template typename ParseHandler::FunctionNodeType GeneralParser::innerFunction( - FunctionNodeType funNode, ParseContext* outerpc, - const ParserAtom* explicitName, FunctionFlags flags, uint32_t toStringStart, - InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind, + 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) { // Note that it is possible for outerpc != this->pc_, as we may be @@ -3130,7 +3101,7 @@ bool GeneralParser::appendToCallSiteObj( return false; } - const ParserAtom* atom = tokenStream.getRawTemplateStringAtom(); + JSAtom* atom = tokenStream.getRawTemplateStringAtom(); if (!atom) { return false; } @@ -3175,20 +3146,10 @@ FunctionNode* Parser::standaloneLazyFunction( return null(); } - // TODO-Stencil: Consider for snapshotting. - const ParserAtom* displayAtom = nullptr; - if (fun->displayAtom()) { - displayAtom = - this->compilationInfo_.lowerJSAtomToParserAtom(fun->displayAtom()); - if (!displayAtom) { - return null(); - } - } - Directives directives(strict); - FunctionBox* funbox = newFunctionBox(funNode, displayAtom, fun->flags(), - toStringStart, directives, generatorKind, - asyncKind, TopLevelFunction::Yes); + FunctionBox* funbox = newFunctionBox( + funNode, fun->displayAtom(), fun->flags(), toStringStart, directives, + generatorKind, asyncKind, TopLevelFunction::Yes); if (!funbox) { return null(); } @@ -3359,7 +3320,7 @@ bool GeneralParser::functionFormalParametersAndBody( "strict mode should only change when a 'use strict' directive " "is present"); - const ParserName* propertyName = funbox->explicitName()->asName(); + PropertyName* propertyName = funbox->explicitName()->asPropertyName(); YieldHandling nameYieldHandling; if (kind == FunctionSyntaxKind::Expression) { // Named lambda has binding inside it. @@ -3466,7 +3427,7 @@ GeneralParser::functionStmt(uint32_t toStringStart, } } - const ParserName* name = nullptr; + RootedPropertyName name(cx_); if (TokenKindIsPossibleIdentifier(tt)) { name = bindingIdentifier(yieldHandling); if (!name) { @@ -3546,7 +3507,7 @@ GeneralParser::functionExpr(uint32_t toStringStart, YieldHandling yieldHandling = GetYieldHandling(generatorKind); - const ParserName* name = nullptr; + RootedPropertyName name(cx_); if (TokenKindIsPossibleIdentifier(tt)) { name = bindingIdentifier(yieldHandling); if (!name) { @@ -3577,14 +3538,13 @@ GeneralParser::functionExpr(uint32_t toStringStart, * isEscapeFreeStringLiteral, below, checks whether the node itself could be * a directive. */ -static inline bool IsEscapeFreeStringLiteral(const TokenPos& pos, - const ParserAtom* atom) { +static inline bool IsEscapeFreeStringLiteral(const TokenPos& pos, JSAtom* str) { /* * If the string's length in the source code is its length as a value, * accounting for the quotes, then it must not contain any escape * sequences or line continuations. */ - return pos.begin + atom->length() + 2 == pos.end; + return pos.begin + str->length() + 2 == pos.end; } template @@ -3634,7 +3594,7 @@ bool Parser::asmJS(ListNodeType list) { // function from the beginning. Reparsing is triggered by marking that a // new directive has been encountered and returning 'false'. bool validated; - if (!CompileAsmJS(cx_, this->compilationInfo_, *this, list, &validated)) { + if (!CompileAsmJS(cx_, *this, list, &validated)) { return false; } if (!validated) { @@ -3673,7 +3633,7 @@ template bool GeneralParser::maybeParseDirective( ListNodeType list, Node possibleDirective, bool* cont) { TokenPos directivePos; - const ParserAtom* directive = + JSAtom* directive = handler_.isStringExprStatement(possibleDirective, &directivePos); *cont = !!directive; @@ -3823,8 +3783,7 @@ typename ParseHandler::Node GeneralParser::condition( template bool GeneralParser::matchLabel( - YieldHandling yieldHandling, const ParserName** labelOut) { - MOZ_ASSERT(labelOut != nullptr); + YieldHandling yieldHandling, MutableHandle label) { TokenKind tt = TokenKind::Eof; if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) { return false; @@ -3833,12 +3792,12 @@ bool GeneralParser::matchLabel( if (TokenKindIsPossibleIdentifier(tt)) { tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp); - *labelOut = labelIdentifier(yieldHandling); - if (!*labelOut) { + label.set(labelIdentifier(yieldHandling)); + if (!label) { return false; } } else { - *labelOut = nullptr; + label.set(nullptr); } return true; } @@ -4002,7 +3961,7 @@ template typename ParseHandler::NameNodeType GeneralParser::bindingIdentifier( DeclarationKind kind, YieldHandling yieldHandling) { - const ParserName* name = bindingIdentifier(yieldHandling); + RootedPropertyName name(cx_, bindingIdentifier(yieldHandling)); if (!name) { return null(); } @@ -4052,7 +4011,7 @@ GeneralParser::objectBindingPattern( } Maybe declKind = Some(kind); - const ParserAtom* propAtom = nullptr; + RootedAtom propAtom(cx_); for (;;) { TokenKind tt; if (!tokenStream.peekToken(&tt)) { @@ -4491,7 +4450,7 @@ typename ParseHandler::Node GeneralParser::declarationName( return null(); } - const ParserName* name = bindingIdentifier(yieldHandling); + RootedPropertyName name(cx_, bindingIdentifier(yieldHandling)); if (!name) { return null(); } @@ -4685,7 +4644,7 @@ bool Parser::namedImportsOrNamespaceImport( return false; } - const ParserName* importName = anyChars.currentName(); + Rooted importName(cx_, anyChars.currentName()); TokenPos importNamePos = pos(); bool matched; @@ -4714,7 +4673,7 @@ bool Parser::namedImportsOrNamespaceImport( } } - const ParserName* bindingAtom = importedBinding(); + RootedPropertyName bindingAtom(cx_, importedBinding()); if (!bindingAtom) { return false; } @@ -4775,7 +4734,7 @@ bool Parser::namedImportsOrNamespaceImport( // definitions that hold a module namespace object. They are treated // as const variables which are initialized during the // ModuleInstantiate step. - const ParserName* bindingName = importedBinding(); + RootedPropertyName bindingName(cx_, importedBinding()); if (!bindingName) { return false; } @@ -4843,7 +4802,7 @@ BinaryNode* Parser::importDeclaration() { return null(); } - const ParserName* bindingAtom = importedBinding(); + RootedPropertyName bindingAtom(cx_, importedBinding()); if (!bindingAtom) { return null(); } @@ -4948,13 +4907,12 @@ GeneralParser::importDeclarationOrImportExpr( } template -bool Parser::checkExportedName( - const ParserAtom* exportName) { +bool Parser::checkExportedName(JSAtom* exportName) { if (!pc_->sc()->asModuleContext()->builder.hasExportedName(exportName)) { return true; } - UniqueChars str = ParserAtomToPrintableString(cx_, exportName); + UniqueChars str = AtomToPrintableString(cx_, exportName); if (!str) { return false; } @@ -4965,14 +4923,14 @@ bool Parser::checkExportedName( template inline bool Parser::checkExportedName( - const ParserAtom* exportName) { + JSAtom* exportName) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } template inline bool GeneralParser::checkExportedName( - const ParserAtom* exportName) { + JSAtom* exportName) { return asFinalParser()->checkExportedName(exportName); } @@ -5287,7 +5245,7 @@ GeneralParser::exportBatch(uint32_t begin) { return null(); } - NameNodeType importName = newName(cx_->parserNames().star); + NameNodeType importName = newName(cx_->names().star); if (!importName) { return null(); } @@ -5323,7 +5281,8 @@ bool Parser::checkLocalExportNames(ListNode* node) { ParseNode* name = next->as().left(); MOZ_ASSERT(name->isKind(ParseNodeKind::Name)); - const ParserName* ident = name->as().atom()->asName(); + RootedPropertyName ident(cx_, + name->as().atom()->asPropertyName()); if (!checkLocalExportName(ident, name->pn_pos.begin)) { return false; } @@ -5667,7 +5626,7 @@ GeneralParser::exportDefaultAssignExpr(uint32_t begin) { return null(); } - const ParserName* name = cx_->parserNames().default_; + HandlePropertyName name = cx_->parserNames().default_; NameNodeType nameNode = newName(name); if (!nameNode) { return null(); @@ -6510,7 +6469,7 @@ GeneralParser::continueStatement( MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Continue)); uint32_t begin = pos().begin; - const ParserName* label = nullptr; + RootedPropertyName label(cx_); if (!matchLabel(yieldHandling, &label)) { return null(); } @@ -6541,7 +6500,7 @@ GeneralParser::breakStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Break)); uint32_t begin = pos().begin; - const ParserName* label = nullptr; + RootedPropertyName label(cx_); if (!matchLabel(yieldHandling, &label)) { return null(); } @@ -6736,7 +6695,7 @@ template typename ParseHandler::LabeledStatementType GeneralParser::labeledStatement( YieldHandling yieldHandling) { - const ParserName* label = labelIdentifier(yieldHandling); + RootedPropertyName label(cx_, labelIdentifier(yieldHandling)); if (!label) { return null(); } @@ -7067,7 +7026,7 @@ static AccessorType ToAccessorType(PropertyType propType) { template bool GeneralParser::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) { *done = false; @@ -7106,7 +7065,7 @@ bool GeneralParser::classMember( return false; } - const ParserAtom* propAtom = nullptr; + RootedAtom propAtom(cx_); PropertyType propType; Node propName = propertyOrMethodName(yieldHandling, PropertyNameInClass, /* maybeDecl = */ Nothing(), @@ -7134,7 +7093,7 @@ bool GeneralParser::classMember( return false; } - const ParserName* privateName = propAtom->asName(); + RootedPropertyName privateName(cx_, propAtom->asPropertyName()); if (!noteDeclaredPrivateName(propName, privateName, propType, pos())) { return false; } @@ -7196,7 +7155,7 @@ bool GeneralParser::classMember( return false; } - const ParserAtom* funName = nullptr; + RootedAtom funName(cx_); switch (propType) { case PropertyType::Getter: case PropertyType::Setter: @@ -7278,7 +7237,7 @@ bool GeneralParser::classMember( return false; } - const ParserName* privateName = propAtom->asName(); + RootedPropertyName privateName(cx_, propAtom->asPropertyName()); if (!noteDeclaredPrivateName(propName, privateName, propType, pos())) { return false; } @@ -7315,9 +7274,9 @@ bool GeneralParser::classMember( default: MOZ_CRASH("Invalid private method accessor type"); } - const ParserAtom* storedMethodAtom = - storedMethodName.finishParserAtom(this->compilationInfo_); - const ParserName* storedMethodProp = storedMethodAtom->asName(); + RootedAtom storedMethodAtom(cx_, storedMethodName.finishAtom()); + RootedPropertyName storedMethodProp(cx_, + storedMethodAtom->asPropertyName()); if (!noteDeclaredName(storedMethodProp, DeclarationKind::Const, pos())) { return false; } @@ -7346,7 +7305,7 @@ bool GeneralParser::classMember( template bool GeneralParser::finishClassConstructor( - const ParseContext::ClassStatement& classStmt, const ParserName* className, + const ParseContext::ClassStatement& classStmt, HandlePropertyName className, HasHeritage hasHeritage, uint32_t classStartOffset, uint32_t classEndOffset, const ClassInitializedMembers& classInitializedMembers, ListNodeType& classMembers) { @@ -7432,7 +7391,7 @@ GeneralParser::classDefinition( return null(); } - const ParserName* className = nullptr; + RootedPropertyName className(cx_); if (TokenKindIsPossibleIdentifier(tt)) { className = bindingIdentifier(yieldHandling); if (!className) { @@ -7607,8 +7566,7 @@ GeneralParser::classDefinition( return null(); } if (maybeUnboundName) { - UniqueChars str = - ParserAtomToPrintableString(cx_, maybeUnboundName->atom); + UniqueChars str = AtomToPrintableString(cx_, maybeUnboundName->atom); if (!str) { return null(); } @@ -7626,8 +7584,7 @@ GeneralParser::classDefinition( template typename ParseHandler::FunctionNodeType GeneralParser::synthesizeConstructor( - const ParserAtom* className, uint32_t classNameOffset, - HasHeritage hasHeritage) { + HandleAtom className, uint32_t classNameOffset, HasHeritage hasHeritage) { FunctionSyntaxKind functionSyntaxKind = hasHeritage == HasHeritage::Yes ? FunctionSyntaxKind::DerivedClassConstructor @@ -7783,7 +7740,7 @@ GeneralParser::synthesizeConstructor( template typename ParseHandler::FunctionNodeType GeneralParser::privateMethodInitializer( - const ParserAtom* propAtom, const ParserAtom* storedMethodAtom) { + HandleAtom propAtom, HandleAtom storedMethodAtom) { // Synthesize an initializer function that the constructor can use to stamp a // private method onto an instance object. FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::FieldInitializer; @@ -7830,11 +7787,11 @@ GeneralParser::privateMethodInitializer( // Note both the stored private method body and it's private name as being // used in the initializer. They will be emitted into the method body in the // BCE. - const ParserName* storedMethodName = storedMethodAtom->asName(); + RootedPropertyName storedMethodName(cx_, storedMethodAtom->asPropertyName()); if (!noteUsedName(storedMethodName)) { return null(); } - const ParserName* privateName = propAtom->asName(); + RootedPropertyName privateName(cx_, propAtom->asPropertyName()); NameNodeType privateNameNode = privateNameReference(privateName); if (!privateNameNode) { return null(); @@ -7881,7 +7838,7 @@ GeneralParser::privateMethodInitializer( template typename ParseHandler::FunctionNodeType GeneralParser::fieldInitializerOpt( - Node propName, const ParserAtom* propAtom, + Node propName, HandleAtom propAtom, ClassInitializedMembers& classInitializedMembers, bool isStatic, HasHeritage hasHeritage) { bool hasInitializer = false; @@ -8042,7 +7999,7 @@ GeneralParser::fieldInitializerOpt( // -first- field in a derived class, which would suffice to match the // semantic check. - const ParserName* privateName = propAtom->asName(); + RootedPropertyName privateName(cx_, propAtom->asPropertyName()); NameNodeType privateNameNode = privateNameReference(privateName); if (!privateNameNode) { return null(); @@ -8060,8 +8017,8 @@ GeneralParser::fieldInitializerOpt( return null(); } } else { - NameNodeType propAssignName = - handler_.newPropertyName(propAtom->asName(), wholeInitializerPos); + NameNodeType propAssignName = handler_.newPropertyName( + propAtom->asPropertyName(), wholeInitializerPos); if (!propAssignName) { return null(); } @@ -8941,7 +8898,7 @@ typename ParseHandler::Node GeneralParser::assignExpr( return null(); } if (endsExpr) { - const ParserName* name = identifierReference(yieldHandling); + Rooted name(cx_, identifierReference(yieldHandling)); if (!name) { return null(); } @@ -9004,7 +8961,7 @@ typename ParseHandler::Node GeneralParser::assignExpr( MOZ_ASSERT(TokenKindIsPossibleIdentifier(tokenAfterAsync)); // Check yield validity here. - const ParserName* name = bindingIdentifier(yieldHandling); + RootedPropertyName name(cx_, bindingIdentifier(yieldHandling)); if (!name) { return null(); } @@ -9797,25 +9754,25 @@ typename ParseHandler::Node GeneralParser::memberExpr( template inline typename ParseHandler::NameNodeType -PerHandlerParser::newName(const ParserName* name) { +PerHandlerParser::newName(PropertyName* name) { return newName(name, pos()); } template inline typename ParseHandler::NameNodeType -PerHandlerParser::newName(const ParserName* name, TokenPos pos) { +PerHandlerParser::newName(PropertyName* name, TokenPos pos) { return handler_.newName(name, pos, cx_); } template inline typename ParseHandler::NameNodeType -PerHandlerParser::newPrivateName(const ParserName* name) { +PerHandlerParser::newPrivateName(PropertyName* name) { return newPrivateName(name, pos()); } template inline typename ParseHandler::NameNodeType -PerHandlerParser::newPrivateName(const ParserName* name, +PerHandlerParser::newPrivateName(PropertyName* name, TokenPos pos) { return handler_.newPrivateName(name, pos); } @@ -9826,7 +9783,7 @@ GeneralParser::memberPropertyAccess( Node lhs, OptionalKind optionalKind /* = OptionalKind::NonOptional */) { MOZ_ASSERT(TokenKindIsPossibleIdentifierName(anyChars.currentToken().type) || anyChars.currentToken().type == TokenKind::PrivateName); - const ParserName* field = anyChars.currentName(); + PropertyName* field = anyChars.currentName(); if (handler_.isSuperBase(lhs) && !checkAndMarkSuperScope()) { error(JSMSG_BAD_SUPERPROP, "property"); return null(); @@ -9850,7 +9807,7 @@ GeneralParser::memberPrivateAccess( Node lhs, OptionalKind optionalKind /* = OptionalKind::NonOptional */) { MOZ_ASSERT(anyChars.currentToken().type == TokenKind::PrivateName); - const ParserName* field = anyChars.currentName(); + RootedPropertyName field(cx_, anyChars.currentName()); // Cannot access private fields on super. if (handler_.isSuperBase(lhs)) { error(JSMSG_BAD_SUPERPRIVATE); @@ -9937,7 +9894,7 @@ typename ParseHandler::Node GeneralParser::memberCall( JSOp op = JSOp::Call; bool maybeAsyncArrow = false; - if (const ParserName* prop = handler_.maybeDottedProperty(lhs)) { + if (PropertyName* prop = handler_.maybeDottedProperty(lhs)) { // Use the JSOp::Fun{Apply,Call} optimizations given the right // syntax. if (prop == cx_->parserNames().apply) { @@ -10022,7 +9979,7 @@ typename ParseHandler::Node GeneralParser::memberCall( template bool GeneralParser::checkLabelOrIdentifierReference( - const ParserName* ident, uint32_t offset, YieldHandling yieldHandling, + PropertyName* ident, uint32_t offset, YieldHandling yieldHandling, TokenKind hint /* = TokenKind::Limit */) { TokenKind tt; if (hint == TokenKind::Limit) { @@ -10100,7 +10057,7 @@ bool GeneralParser::checkLabelOrIdentifierReference( template bool GeneralParser::checkBindingIdentifier( - const ParserName* ident, uint32_t offset, YieldHandling yieldHandling, + PropertyName* ident, uint32_t offset, YieldHandling yieldHandling, TokenKind hint /* = TokenKind::Limit */) { if (pc_->sc()->strict()) { if (ident == cx_->parserNames().arguments) { @@ -10122,21 +10079,21 @@ bool GeneralParser::checkBindingIdentifier( } template -const ParserName* GeneralParser::labelOrIdentifierReference( +PropertyName* GeneralParser::labelOrIdentifierReference( YieldHandling yieldHandling) { // ES 2017 draft 12.1.1. // StringValue of IdentifierName normalizes any Unicode escape sequences // in IdentifierName hence such escapes cannot be used to write an // Identifier whose code point sequence is the same as a ReservedWord. // - // Use const ParserName* instead of TokenKind to reflect the normalization. + // Use PropertyName* instead of TokenKind to reflect the normalization. // Unless the name contains escapes, we can reuse the current TokenKind // to determine if the name is a restricted identifier. TokenKind hint = !anyChars.currentNameHasEscapes() ? anyChars.currentToken().type : TokenKind::Limit; - const ParserName* ident = anyChars.currentName(); + RootedPropertyName ident(cx_, anyChars.currentName()); if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling, hint)) { return nullptr; @@ -10145,12 +10102,12 @@ const ParserName* GeneralParser::labelOrIdentifierReference( } template -const ParserName* GeneralParser::bindingIdentifier( +PropertyName* GeneralParser::bindingIdentifier( YieldHandling yieldHandling) { TokenKind hint = !anyChars.currentNameHasEscapes() ? anyChars.currentToken().type : TokenKind::Limit; - const ParserName* ident = anyChars.currentName(); + RootedPropertyName ident(cx_, anyChars.currentName()); if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint)) { return nullptr; } @@ -10159,7 +10116,8 @@ const ParserName* GeneralParser::bindingIdentifier( template typename ParseHandler::NameNodeType -PerHandlerParser::identifierReference(const ParserName* name) { +PerHandlerParser::identifierReference( + Handle name) { NameNodeType id = newName(name); if (!id) { return null(); @@ -10174,7 +10132,8 @@ PerHandlerParser::identifierReference(const ParserName* name) { template typename ParseHandler::NameNodeType -PerHandlerParser::privateNameReference(const ParserName* name) { +PerHandlerParser::privateNameReference( + Handle name) { NameNodeType id = newPrivateName(name); if (!id) { return null(); @@ -10320,15 +10279,7 @@ GeneralParser::newBigInt() { } template -const ParserAtom* GeneralParser::bigIntAtom() { - // TODO-Stencil: In progress on Bug 1659595. - // - // This implementation needs to be changed to do either a direct translation - // of the atom, or the parser in general fixed to not require normalized - // bigint atoms, and this code changed to return the raw character data as - // an atom (or more appropriately: this method removed and its user - // changed to just create a regular string atom). - +JSAtom* GeneralParser::bigIntAtom() { // See newBigInt() for a description about |chars'| contents. const auto& chars = tokenStream.getCharBuffer(); mozilla::Range source(chars.begin(), chars.length()); @@ -10337,11 +10288,7 @@ const ParserAtom* GeneralParser::bigIntAtom() { if (!bi) { return nullptr; } - RootedAtom atom(cx_, BigIntToAtom(cx_, bi)); - if (!atom) { - return nullptr; - } - return this->compilationInfo_.lowerJSAtomToParserAtom(atom.get()); + return BigIntToAtom(cx_, bi); } // |exprPossibleError| is the PossibleError state within |expr|, @@ -10592,7 +10539,7 @@ template typename ParseHandler::Node GeneralParser::propertyName( YieldHandling yieldHandling, PropertyNameContext propertyNameContext, const Maybe& maybeDecl, ListNodeType propList, - const ParserAtom** propAtomOut) { + MutableHandleAtom propAtom) { // PropertyName[Yield, Await]: // LiteralPropertyName // ComputedPropertyName[?Yield, ?Await] @@ -10603,29 +10550,26 @@ typename ParseHandler::Node GeneralParser::propertyName( // NumericLiteral TokenKind ltok = anyChars.currentToken().type; - *propAtomOut = nullptr; + propAtom.set(nullptr); switch (ltok) { - case TokenKind::Number: { - const ParserAtom* numAtom = NumberToParserAtom( - this->compilationInfo_, anyChars.currentToken().number()); - if (!numAtom) { + case TokenKind::Number: + propAtom.set(NumberToAtom(cx_, anyChars.currentToken().number())); + if (!propAtom.get()) { return null(); } - *propAtomOut = numAtom; return newNumber(anyChars.currentToken()); - } case TokenKind::BigInt: - *propAtomOut = bigIntAtom(); - if (!*propAtomOut) { + propAtom.set(bigIntAtom()); + if (!propAtom.get()) { return null(); } return newBigInt(); case TokenKind::String: { - *propAtomOut = anyChars.currentToken().atom(); + propAtom.set(anyChars.currentToken().atom()); uint32_t index; - if ((*propAtomOut)->isIndex(&index)) { + if (propAtom->isIndex(&index)) { return handler_.newNumber(index, NoDecimal, pos()); } return stringLiteral(); @@ -10641,8 +10585,8 @@ typename ParseHandler::Node GeneralParser::propertyName( return null(); } - const ParserName* propName = anyChars.currentName()->asName(); - *propAtomOut = propName; + propAtom.set(anyChars.currentName()); + RootedPropertyName propName(cx_, propAtom->asPropertyName()); return privateNameReference(propName); } @@ -10652,8 +10596,8 @@ typename ParseHandler::Node GeneralParser::propertyName( return null(); } - *propAtomOut = anyChars.currentName(); - return handler_.newObjectLiteralPropertyName(*propAtomOut, pos()); + propAtom.set(anyChars.currentName()); + return handler_.newObjectLiteralPropertyName(propAtom, pos()); } } } @@ -10671,7 +10615,7 @@ typename ParseHandler::Node GeneralParser::propertyOrMethodName( YieldHandling yieldHandling, PropertyNameContext propertyNameContext, const Maybe& maybeDecl, ListNodeType propList, - PropertyType* propType, const ParserAtom** propAtomOut) { + PropertyType* propType, MutableHandleAtom propAtom) { // We're parsing an object literal, class, or destructuring pattern; // propertyNameContext tells which one. This method parses any of the // following, storing the corresponding PropertyType in `*propType` to tell @@ -10755,7 +10699,7 @@ GeneralParser::propertyOrMethodName( } Node propName = propertyName(yieldHandling, propertyNameContext, maybeDecl, - propList, propAtomOut); + propList, propAtom); if (!propName) { return null(); } @@ -10869,7 +10813,7 @@ GeneralParser::objectLiteral(YieldHandling yieldHandling, bool seenPrototypeMutation = false; bool seenCoverInitializedName = false; Maybe declKind = Nothing(); - const ParserAtom* propAtom = nullptr; + RootedAtom propAtom(cx_); for (;;) { TokenKind tt; if (!tokenStream.peekToken(&tt)) { @@ -10971,7 +10915,7 @@ GeneralParser::objectLiteral(YieldHandling yieldHandling, * for |({x: x, y: y} = o)|, and |var o = {x, y}| as * initializer shorthand for |var o = {x: x, y: y}|. */ - const ParserName* name = identifierReference(yieldHandling); + Rooted name(cx_, identifierReference(yieldHandling)); if (!name) { return null(); } @@ -10994,7 +10938,7 @@ GeneralParser::objectLiteral(YieldHandling yieldHandling, * Support, e.g., |({x=1, y=2} = o)| as destructuring * shorthand with default values, as per ES6 12.14.5 */ - const ParserName* name = identifierReference(yieldHandling); + Rooted name(cx_, identifierReference(yieldHandling)); if (!name) { return null(); } @@ -11052,7 +10996,7 @@ GeneralParser::objectLiteral(YieldHandling yieldHandling, return null(); } } else { - const ParserAtom* funName = nullptr; + RootedAtom funName(cx_); if (!anyChars.isCurrentTokenType(TokenKind::RightBracket)) { funName = propAtom; @@ -11114,7 +11058,7 @@ template typename ParseHandler::FunctionNodeType GeneralParser::methodDefinition(uint32_t toStringStart, PropertyType propType, - const ParserAtom* funName) { + HandleAtom funName) { FunctionSyntaxKind syntaxKind; switch (propType) { case PropertyType::Getter: @@ -11358,7 +11302,7 @@ typename ParseHandler::Node GeneralParser::primaryExpr( } } - const ParserName* name = identifierReference(yieldHandling); + Rooted name(cx_, identifierReference(yieldHandling)); if (!name) { return null(); } diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 916207bfc673..26be3df7b7a9 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -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 newGlobalScopeData( + mozilla::Maybe newGlobalScopeData( ParseContext::Scope& scope); - mozilla::Maybe newModuleScopeData( + mozilla::Maybe newModuleScopeData( ParseContext::Scope& scope); - mozilla::Maybe newEvalScopeData( - ParseContext::Scope& scope); - mozilla::Maybe newFunctionScopeData( + mozilla::Maybe newEvalScopeData(ParseContext::Scope& scope); + mozilla::Maybe newFunctionScopeData( ParseContext::Scope& scope, bool hasParameterExprs); - mozilla::Maybe newVarScopeData( - ParseContext::Scope& scope); - mozilla::Maybe newLexicalScopeData( + mozilla::Maybe newVarScopeData(ParseContext::Scope& scope); + mozilla::Maybe 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 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 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 name); + NameNodeType privateNameReference(Handle 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 { 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 { 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 { 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 { 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 { 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 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 { 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 { Node propertyName(YieldHandling yieldHandling, PropertyNameContext propertyNameContext, const mozilla::Maybe& maybeDecl, - ListNodeType propList, const ParserAtom** propAtomOut); + ListNodeType propList, MutableHandleAtom propAtom); Node propertyOrMethodName(YieldHandling yieldHandling, PropertyNameContext propertyNameContext, const mozilla::Maybe& maybeDecl, ListNodeType propList, PropertyType* propType, - const ParserAtom** propAtomOut); + MutableHandleAtom propAtom); UnaryNodeType computedPropertyName( YieldHandling yieldHandling, const mozilla::Maybe& maybeDecl, @@ -1377,7 +1366,7 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { inline BigIntLiteralType newBigInt(); - const ParserAtom* bigIntAtom(); + JSAtom* bigIntAtom(); enum class OptionalKind { NonOptional = 0, @@ -1398,18 +1387,17 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser { // 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 { // 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 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 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 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 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 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 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 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); + +VarScope::Data* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings); + +LexicalScope::Data* NewEmptyLexicalScopeData(JSContext* cx, LifoAlloc& alloc, + uint32_t numBindings); + +FunctionScope::Data* NewEmptyFunctionScopeData(JSContext* cx, LifoAlloc& alloc, uint32_t numBindings); -ParserVarScopeData* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc, - uint32_t numBindings); - -ParserLexicalScopeData* NewEmptyLexicalScopeData(JSContext* cx, - LifoAlloc& alloc, - uint32_t numBindings); - -ParserFunctionScopeData* NewEmptyFunctionScopeData(JSContext* cx, - LifoAlloc& alloc, - uint32_t numBindings); - -mozilla::Maybe NewGlobalScopeData( +mozilla::Maybe NewGlobalScopeData( JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc, ParseContext* pc); - -mozilla::Maybe NewEvalScopeData( - JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc, - ParseContext* pc); - -mozilla::Maybe NewFunctionScopeData( +mozilla::Maybe NewEvalScopeData(JSContext* context, + ParseContext::Scope& scope, + LifoAlloc& alloc, + ParseContext* pc); +mozilla::Maybe NewFunctionScopeData( JSContext* context, ParseContext::Scope& scope, bool hasParameterExprs, LifoAlloc& alloc, ParseContext* pc); - -mozilla::Maybe NewVarScopeData(JSContext* context, - ParseContext::Scope& scope, - LifoAlloc& alloc, - ParseContext* pc); - -mozilla::Maybe NewLexicalScopeData( +mozilla::Maybe NewVarScopeData(JSContext* context, + ParseContext::Scope& scope, + LifoAlloc& alloc, + ParseContext* pc); +mozilla::Maybe NewLexicalScopeData( JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc, ParseContext* pc); diff --git a/js/src/frontend/ParserAtom.cpp b/js/src/frontend/ParserAtom.cpp index 309fd04bad1e..875debd1c52a 100644 --- a/js/src/frontend/ParserAtom.cpp +++ b/js/src/frontend/ParserAtom.cpp @@ -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 ParserAtomsTable::concatAtoms( - JSContext* cx, mozilla::Range 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 buf[ParserAtomEntry::MaxInline()]; - 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 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 seq(copy.get(), catLen); @@ -380,11 +376,8 @@ JS::Result ParserAtomsTable::concatAtoms( if (catLen <= ParserAtomEntry::MaxInline()) { char16_t buf[ParserAtomEntry::MaxInline()]; - size_t offset = 0; - for (const ParserAtom* atom : atoms) { - FillChar16Buffer(buf + offset, atom); - offset += atom->length(); - } + FillChar16Buffer(buf, prefix); + FillChar16Buffer(buf + prefixLength, suffix); InflatedChar16Sequence seq(buf, catLen); @@ -406,11 +399,8 @@ JS::Result 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 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(); @@ -489,16 +478,16 @@ bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name, } bool WellKnownParserAtoms::init(JSContext* cx) { -#define COMMON_NAME_INIT_(idpart, id, text) \ - if (!initSingle(cx, &(id), text, cx->names().id)) { \ - return false; \ +#define COMMON_NAME_INIT_(idpart, id, text) \ + if (!initSingle(cx, &(id), text)) { \ + return false; \ } FOR_EACH_COMMON_PROPERTYNAME(COMMON_NAME_INIT_) #undef COMMON_NAME_INIT_ -#define COMMON_NAME_INIT_(name, clasp) \ - if (!initSingle(cx, &(name), #name, cx->names().name)) { \ - return false; \ +#define COMMON_NAME_INIT_(name, clasp) \ + if (!initSingle(cx, &(name), #name)) { \ + return false; \ } JS_FOR_EACH_PROTOTYPE(COMMON_NAME_INIT_) #undef 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 } diff --git a/js/src/frontend/ParserAtom.h b/js/src/frontend/ParserAtom.h index adf55bea5627..bde758aee770 100644 --- a/js/src/frontend/ParserAtom.h +++ b/js/src/frontend/ParserAtom.h @@ -9,14 +9,12 @@ #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 +#include "ds/LifoAlloc.h" // LifoAlloc +#include "js/HashTable.h" // HashSet +#include "js/UniquePtr.h" // js::UniquePtr +#include "js/Vector.h" // Vector #include "vm/CommonPropertyNames.h" #include "vm/StringType.h" // CompareChars, StringEqualsAscii @@ -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 ParserAtomEntry(mozilla::UniquePtr chars, uint32_t length, HashNumber hash) @@ -256,12 +249,6 @@ class alignas(alignof(void*)) ParserAtomEntry { MOZ_ASSERT(hasTwoByteChars()); return variant_.getUnchecked(); } - mozilla::Range latin1Range() const { - return mozilla::Range(latin1Chars(), length_); - } - mozilla::Range 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 internJSAtom(JSContext* cx, JSAtom* atom); - JS::Result concatAtoms( - JSContext* cx, mozilla::Range atoms); + JS::Result concatAtoms(JSContext* cx, + const ParserAtom* prefix, + const ParserAtom* suffix); }; template @@ -515,11 +502,4 @@ inline bool ParserAtomEntry::equalsSeq( } /* namespace frontend */ } /* namespace js */ -namespace JS { -// Dummy trace policy until tracing is removed. -template <> -struct GCPolicy - : IgnoreGCPolicy {}; -} // namespace JS - #endif // frontend_ParserAtom_h diff --git a/js/src/frontend/PropOpEmitter.cpp b/js/src/frontend/PropOpEmitter.cpp index 149168941a9e..94798c7243fa 100644 --- a/js/src/frontend/PropOpEmitter.cpp +++ b/js/src/frontend/PropOpEmitter.cpp @@ -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()); diff --git a/js/src/frontend/PropOpEmitter.h b/js/src/frontend/PropOpEmitter.h index 08f2f226106a..7d346df3c4aa 100644 --- a/js/src/frontend/PropOpEmitter.h +++ b/js/src/frontend/PropOpEmitter.h @@ -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 */ diff --git a/js/src/frontend/SharedContext-inl.h b/js/src/frontend/SharedContext-inl.h index 2033c6d1321f..9175fcc0e2ef 100644 --- a/js/src/frontend/SharedContext-inl.h +++ b/js/src/frontend/SharedContext-inl.h @@ -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 diff --git a/js/src/frontend/SharedContext.cpp b/js/src/frontend/SharedContext.cpp index 75df5eae809c..f161c3f52397 100644 --- a/js/src/frontend/SharedContext.cpp +++ b/js/src/frontend/SharedContext.cpp @@ -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); diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index dce48b92fac3..7dd44ccf71c8 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -107,21 +107,6 @@ class GlobalSharedContext; class EvalSharedContext; class ModuleSharedContext; -using ParserBindingName = AbstractBindingName; -using ParserBindingIter = AbstractBindingIter; - -using BaseParserScopeData = AbstractBaseScopeData; - -template -using ParserScopeData = typename Scope::template AbstractData; - -using ParserGlobalScopeData = ParserScopeData; -using ParserEvalScopeData = ParserScopeData; -using ParserLexicalScopeData = ParserScopeData; -using ParserFunctionScopeData = ParserScopeData; -using ParserModuleScopeData = ParserScopeData; -using ParserVarScopeData = ParserScopeData; - #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 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 bindings; EvalSharedContext(JSContext* cx, CompilationInfo& compilationInfo, Directives directives, SourceExtent extent); @@ -341,20 +323,20 @@ class FunctionBox : public SharedContext { mozilla::Maybe 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 functionStencil() const; @@ -439,21 +421,22 @@ class FunctionBox : public SharedContext { bool atomsAreKept(); #endif - ParserLexicalScopeData* namedLambdaBindings() { return namedLambdaBindings_; } - void setNamedLambdaBindings(ParserLexicalScopeData* bindings) { - namedLambdaBindings_ = bindings; + MutableHandle namedLambdaBindings() { + MOZ_ASSERT(atomsAreKept()); + return MutableHandle::fromMarkedLocation( + &namedLambdaBindings_); } - ParserFunctionScopeData* functionScopeBindings() { - return functionScopeBindings_; - } - void setFunctionScopeBindings(ParserFunctionScopeData* bindings) { - functionScopeBindings_ = bindings; + MutableHandle functionScopeBindings() { + MOZ_ASSERT(atomsAreKept()); + return MutableHandle::fromMarkedLocation( + &functionScopeBindings_); } - ParserVarScopeData* extraVarScopeBindings() { return extraVarScopeBindings_; } - void setExtraVarScopeBindings(ParserVarScopeData* bindings) { - extraVarScopeBindings_ = bindings; + MutableHandle extraVarScopeBindings() { + MOZ_ASSERT(atomsAreKept()); + return MutableHandle::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) { diff --git a/js/src/frontend/Stencil.cpp b/js/src/frontend/Stencil.cpp index ebd977c172d4..bc4959607f4c 100644 --- a/js/src/frontend/Stencil.cpp +++ b/js/src/frontend/Stencil.cpp @@ -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().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().trace(trc); + break; + } + case ScopeKind::FunctionBodyVar: { + data().trace(trc); + break; + } + case ScopeKind::Global: + case ScopeKind::NonSyntactic: { + data().trace(trc); + break; + } + case ScopeKind::Eval: + case ScopeKind::StrictEval: { + data().trace(trc); + break; + } + case ScopeKind::Module: { + data().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()) { + JSAtom* atom = thing.as(); + TraceRoot(trc, &atom, "script-atom"); + MOZ_ASSERT(atom == thing.as(), "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* trailingNames = nullptr; + AbstractTrailingNamesArray* trailingNames = nullptr; uint32_t length = 0; switch (kind_) { case ScopeKind::Function: { - auto* data = static_cast(data_); + auto* data = static_cast(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(data_); + auto* data = static_cast(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(data_); + auto* data = static_cast(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(data_); + auto* data = static_cast(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(data_); + auto* data = static_cast(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(data_); + auto* data = static_cast(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*>( - data_); + auto* data = static_cast(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*>( - data_); + auto* data = static_cast(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(); diff --git a/js/src/frontend/Stencil.h b/js/src/frontend/Stencil.h index 6bff39f6120c..3ca4847e27e8 100644 --- a/js/src/frontend/Stencil.h +++ b/js/src/frontend/Stencil.h @@ -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; - -template -using ParserScopeData = typename Scope::template AbstractData; -using ParserGlobalScopeData = ParserScopeData; -using ParserEvalScopeData = ParserScopeData; -using ParserLexicalScopeData = ParserScopeData; -using ParserFunctionScopeData = ParserScopeData; -using ParserModuleScopeData = ParserScopeData; -using ParserVarScopeData = ParserScopeData; - -using ParserBindingIter = AbstractBindingIter; - // [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 data_; public: ScopeStencil(ScopeKind kind, mozilla::Maybe enclosing, uint32_t firstFrameSlot, mozilla::Maybe numEnvironmentSlots, - BaseParserScopeData* data = {}, + UniquePtr data = {}, mozilla::Maybe 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 dataArg, bool hasParameterExprs, bool needsEnvironment, FunctionIndex functionIndex, bool isArrow, mozilla::Maybe enclosing, ScopeIndex* index); static bool createForLexicalScope( JSContext* cx, CompilationInfo& compilationInfo, ScopeKind kind, - ParserLexicalScopeData* dataArg, uint32_t firstFrameSlot, + Handle dataArg, uint32_t firstFrameSlot, mozilla::Maybe 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 dataArg, uint32_t firstFrameSlot, bool needsEnvironment, mozilla::Maybe enclosing, ScopeIndex* index); @@ -218,18 +201,19 @@ class ScopeStencil { static bool createForGlobalScope(JSContext* cx, CompilationInfo& compilationInfo, ScopeKind kind, - ParserGlobalScopeData* dataArg, + Handle dataArg, ScopeIndex* index); static bool createForEvalScope(JSContext* cx, CompilationInfo& compilationInfo, - ScopeKind kind, ParserEvalScopeData* dataArg, + ScopeKind kind, + Handle dataArg, mozilla::Maybe enclosing, ScopeIndex* index); static bool createForModuleScope(JSContext* cx, CompilationInfo& compilationInfo, - ParserModuleScopeData* dataArg, + Handle dataArg, mozilla::Maybe enclosing, ScopeIndex* index); @@ -266,19 +250,15 @@ class ScopeStencil { private: // Non owning reference to data template - typename SpecificScopeType::template AbstractData& data() - const { - using Data = - typename SpecificScopeType ::template AbstractData; - - MOZ_ASSERT(data_); - return *static_cast(data_); + typename SpecificScopeType::Data& data() const { + MOZ_ASSERT(data_.get()); + return *static_cast(data_.get()); } // Transfer ownership into a new UniquePtr. template - UniquePtr createSpecificScopeData( - JSContext* cx, CompilationInfo& compilationInfo); + UniquePtr releaseData( + CompilationInfo& compilationInfo); template 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 module); + bool initModule(JSContext* cx, JS::Handle 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 = {}; diff --git a/js/src/frontend/SwitchEmitter.cpp b/js/src/frontend/SwitchEmitter.cpp index 11c78fddefb0..95160ce885ea 100644 --- a/js/src/frontend/SwitchEmitter.cpp +++ b/js/src/frontend/SwitchEmitter.cpp @@ -122,7 +122,7 @@ bool SwitchEmitter::emitDiscriminant(const Maybe& switchPos) { return true; } -bool SwitchEmitter::emitLexical(ParserLexicalScopeData* bindings) { +bool SwitchEmitter::emitLexical(Handle bindings) { MOZ_ASSERT(state_ == State::Discriminant); MOZ_ASSERT(bindings); diff --git a/js/src/frontend/SwitchEmitter.h b/js/src/frontend/SwitchEmitter.h index 2cd5a9b0dc5c..b52016fa8013 100644 --- a/js/src/frontend/SwitchEmitter.h +++ b/js/src/frontend/SwitchEmitter.h @@ -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 bindings); MOZ_MUST_USE bool emitCond(); MOZ_MUST_USE bool emitTable(const TableGenerator& tableGen); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 6cf049b84d72..df303abcfc0d 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -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; diff --git a/js/src/frontend/TDZCheckCache.cpp b/js/src/frontend/TDZCheckCache.cpp index 6cb4abfc50dd..8974ef74de88 100644 --- a/js/src/frontend/TDZCheckCache.cpp +++ b/js/src/frontend/TDZCheckCache.cpp @@ -24,7 +24,7 @@ bool TDZCheckCache::ensureCache(BytecodeEmitter* bce) { } Maybe TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, - const ParserAtom* name) { + JSAtom* name) { if (!ensureCache(bce)) { return Nothing(); } @@ -52,7 +52,7 @@ Maybe 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; diff --git a/js/src/frontend/TDZCheckCache.h b/js/src/frontend/TDZCheckCache.h index b8c143c80b06..87f74f061904 100644 --- a/js/src/frontend/TDZCheckCache.h +++ b/js/src/frontend/TDZCheckCache.h @@ -47,8 +47,8 @@ class TDZCheckCache : public Nestable { explicit TDZCheckCache(BytecodeEmitter* bce); mozilla::Maybe 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); }; diff --git a/js/src/frontend/Token.h b/js/src/frontend/Token.h index 5d8db585d8d4..1b28d59790c1 100644 --- a/js/src/frontend/Token.h +++ b/js/src/frontend/Token.h @@ -16,9 +16,9 @@ #include // uint32_t -#include "frontend/ParserAtom.h" // js::frontend::{ParserAtom,ParserName} -#include "frontend/TokenKind.h" // js::frontend::TokenKind -#include "js/RegExpFlags.h" // JS::RegExpFlags +#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; diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index 6d892f6e6805..8613bb8a10f1 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -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,10 +125,22 @@ MOZ_ALWAYS_INLINE const ReservedWordInfo* FindReservedWord( return FindReservedWord(Utf8AsUnsignedChars(units), length); } -template 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); + } + + const char16_t* chars = str->twoByteChars(nogc); + size_t length = str->length(); if (length > 0 && chars[0] == '#') { *visibility = js::frontend::NameVisibility::Private; return nullptr; @@ -138,24 +149,6 @@ static const ReservedWordInfo* FindReservedWord( 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); - } - return FindReservedWord(atom->twoByteChars(), atom->length(), visibility); -} - static uint32_t GetSingleCodePoint(const char16_t** p, const char16_t* end) { using namespace js; @@ -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::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::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::getStringOrTemplateToken( } } - const ParserAtom* atom = drainCharBufferIntoAtom(); + JSAtom* atom = drainCharBufferIntoAtom(); if (!atom) { return false; } diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index 7697a9e5fc9d..d0012ec717b0 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -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(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 units); + MOZ_ALWAYS_INLINE JSAtom* atomizeSourceChars(mozilla::Span units); /** * Try to match a non-LineTerminator ASCII code point. Return true iff it @@ -1696,21 +1701,45 @@ inline void TokenStreamCharsBase::consumeKnownCodeUnit(int32_t unit) { } template <> -MOZ_ALWAYS_INLINE const ParserAtom* -TokenStreamCharsBase::atomizeSourceChars( +MOZ_ALWAYS_INLINE JSAtom* TokenStreamCharsBase::atomizeSourceChars( mozilla::Span 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::atomizeSourceChars( mozilla::Span 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 @@ -1994,7 +2023,7 @@ class GeneralTokenStreamChars : public SpecializedTokenStreamCharsBase { 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 { 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 { */ void consumeOptionalHashbangComment(); - const ParserAtom* getRawTemplateStringAtom() { + JSAtom* getRawTemplateStringAtom() { TokenStreamAnyChars& anyChars = anyCharsAccess(); MOZ_ASSERT(anyChars.currentToken().type == TokenKind::TemplateHead || diff --git a/js/src/frontend/UsedNameTracker.h b/js/src/frontend/UsedNameTracker.h index c3c123cbe92a..f34e371a855e 100644 --- a/js/src/frontend/UsedNameTracker.h +++ b/js/src/frontend/UsedNameTracker.h @@ -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 pos() { return firstUsePos_; } }; - using UsedNameMap = HashMap>; + using UsedNameMap = HashMap>; 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 tokenPosition = mozilla::Nothing()); // Fill maybeUnboundName with the first (source order) unbound name, or diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index b4d2518225b6..2808748d7b00 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -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; } diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index ffbab3dd8796..425e7a482a98 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -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 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); diff --git a/js/src/jsnum.h b/js/src/jsnum.h index b8df65fec437..223985c80ab2 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -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 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); diff --git a/js/src/util/StringBuffer.cpp b/js/src/util/StringBuffer.cpp index 93a1938cc26a..25fc02375ed3 100644 --- a/js/src/util/StringBuffer.cpp +++ b/js/src/util/StringBuffer.cpp @@ -12,8 +12,6 @@ #include -#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 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); diff --git a/js/src/util/StringBuffer.h b/js/src/util/StringBuffer.h index 95febf45eaf4..cce6269da437 100644 --- a/js/src/util/StringBuffer.h +++ b/js/src/util/StringBuffer.h @@ -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(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 diff --git a/js/src/vm/BuiltinObjectKind.cpp b/js/src/vm/BuiltinObjectKind.cpp index c9d17f180e0f..1dd1dadc5dd0 100644 --- a/js/src/vm/BuiltinObjectKind.cpp +++ b/js/src/vm/BuiltinObjectKind.cpp @@ -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; } } diff --git a/js/src/vm/BuiltinObjectKind.h b/js/src/vm/BuiltinObjectKind.h index 3f559c0806ee..5621fc0418d1 100644 --- a/js/src/vm/BuiltinObjectKind.h +++ b/js/src/vm/BuiltinObjectKind.h @@ -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 diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index ce120d5a6b31..50113a26ef54 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -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() const { is(); } -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; } diff --git a/js/src/vm/GeneratorObject.h b/js/src/vm/GeneratorObject.h index 9c23b82f533a..e24b72e42896 100644 --- a/js/src/vm/GeneratorObject.h +++ b/js/src/vm/GeneratorObject.h @@ -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 diff --git a/js/src/vm/Instrumentation.cpp b/js/src/vm/Instrumentation.cpp index d76846224148..415cf21984a3 100644 --- a/js/src/vm/Instrumentation.cpp +++ b/js/src/vm/Instrumentation.cpp @@ -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"); diff --git a/js/src/vm/Instrumentation.h b/js/src/vm/Instrumentation.h index 55c408d56366..31870293810b 100644 --- a/js/src/vm/Instrumentation.h +++ b/js/src/vm/Instrumentation.h @@ -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 global, HandleScript script, int32_t* id); diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h index affcba22ea6b..3957711d8f83 100644 --- a/js/src/vm/JSContext.h +++ b/js/src/vm/JSContext.h @@ -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(); diff --git a/js/src/vm/ModuleBuilder.h b/js/src/vm/ModuleBuilder.h index 8f09dc7ab31a..0a46a1dbf7da 100644 --- a/js/src/vm/ModuleBuilder.h +++ b/js/src/vm/ModuleBuilder.h @@ -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; - using AtomSet = JS::GCHashSet; + using AtomSet = JS::GCHashSet; using ExportEntryVector = GCVector; - using ImportEntryMap = - JS::GCHashMap; + using ImportEntryMap = JS::GCHashMap; using RootedExportEntryVector = JS::Rooted; using RootedRequestedModuleVector = JS::Rooted; using RootedAtomSet = JS::Rooted; @@ -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 exportName, + JS::Handle localName, frontend::ParseNode* node = nullptr); - bool appendExportFromEntry(const frontend::ParserAtom* exportName, - const frontend::ParserAtom* moduleRequest, - const frontend::ParserAtom* importName, + bool appendExportFromEntry(JS::Handle exportName, + JS::Handle moduleRequest, + JS::Handle importName, frontend::ParseNode* node); - bool maybeAppendRequestedModule(const frontend::ParserAtom* specifier, + bool maybeAppendRequestedModule(JS::Handle specifier, frontend::ParseNode* node); }; diff --git a/js/src/vm/Printer.cpp b/js/src/vm/Printer.cpp index 427fd62e6d18..2c97b4a2a2eb 100644 --- a/js/src/vm/Printer.cpp +++ b/js/src/vm/Printer.cpp @@ -14,7 +14,6 @@ #include #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(sp, atom->latin1Range(), quote) - : QuoteString(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) { diff --git a/js/src/vm/Printer.h b/js/src/vm/Printer.h index d2838766a18f..5de557a930d2 100644 --- a/js/src/vm/Printer.h +++ b/js/src/vm/Printer.h @@ -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); diff --git a/js/src/vm/Scope.cpp b/js/src/vm/Scope.cpp index a1bb68f4b233..9f76a6fb6726 100644 --- a/js/src/vm/Scope.cpp +++ b/js/src/vm/Scope.cpp @@ -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& 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 inline size_t SizeOfAllocatedData(Data* data) { - return SizeOfScopeData(data->length); -} - -template -static UniquePtr> CopyScopeDataImpl( - JSContext* cx, AbstractScopeData* data) { - using Data = AbstractScopeData; - - size_t size = SizeOfAllocatedData(data); - void* bytes = cx->pod_malloc(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(dataCopy); + return SizeOfData(data->length); } template @@ -215,13 +163,18 @@ static UniquePtr CopyScopeData( cx->markAtom(name); } } - return CopyScopeDataImpl(cx, data); -} -template -static UniquePtr> CopyScopeData( - JSContext* cx, ParserScopeData* data) { - return CopyScopeDataImpl(cx, data); + size_t size = SizeOfAllocatedData(data); + void* bytes = cx->pod_malloc(size); + if (!bytes) { + return nullptr; + } + + auto* dataCopy = new (bytes) typename ConcreteScope::Data(*data); + + std::uninitialized_copy_n(names, length, dataCopy->trailingNames.start()); + + return UniquePtr(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* envShape) { @@ -243,17 +196,16 @@ static bool SetEnvironmentShape(JSContext* cx, ParserBindingIter& freshBi, return true; } -template +template static bool PrepareScopeData( - JSContext* cx, AbstractBindingIter& bi, - typename MaybeRootedScopeData::HandleType data, - uint32_t firstFrameSlot, ShapeT envShape) { - const JSClass* cls = &EnvironmentT::class_; - uint32_t baseShapeFlags = EnvironmentT::BASESHAPE_FLAGS; + JSContext* cx, BindingIter& bi, + Handle> 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 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 -static UniquePtr> NewEmptyScopeData( - JSContext* cx, uint32_t length = 0) { - using Data = AbstractScopeData; - - size_t dataSize = SizeOfScopeData(length); - uint8_t* bytes = cx->pod_malloc(dataSize); - auto data = reinterpret_cast(bytes); - if (data) { - new (data) Data(length); - } - return UniquePtr(data); -} - template -static UniquePtr LiftParserScopeData( - JSContext* cx, ParserScopeData* data) { - using ConcreteData = typename ConcreteScope::Data; - - // Convert all scope ParserAtoms to rooted JSAtoms. - // Rooting is necessary as conversion can gc. - JS::RootedVector jsatoms(cx); - if (!jsatoms.reserve(data->length)) { - return nullptr; +static UniquePtr NewEmptyScopeData( + JSContext* cx, uint32_t length = 0) { + size_t dataSize = SizeOfData(length); + uint8_t* bytes = cx->pod_malloc(dataSize); + auto data = reinterpret_cast(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 scopeData( - NewEmptyScopeData(cx, data->length)); - if (!scopeData) { - return nullptr; - } - - // Memcopy the head of the structure directly, no translation needed. - static_assert(sizeof(ConcreteData) == sizeof(ParserScopeData), - "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(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(cx, length).release()); + data.set(NewEmptyScopeData(cx, length).release()); if (!data) { return xdr->fail(JS::TranscodeResult_Throw); } @@ -468,11 +370,11 @@ inline void Scope::initData( setHeaderPtr(data.get().release()); } -template +template bool Scope::updateEnvShapeIfRequired(JSContext* cx, MutableHandleShape envShape, bool needsEnvironment) { if (!envShape && needsEnvironment) { - envShape.set(EmptyEnvironmentShape(cx)); + envShape.set(EmptyEnvironmentShape(cx)); if (!envShape) { return false; } @@ -480,7 +382,7 @@ bool Scope::updateEnvShapeIfRequired(JSContext* cx, MutableHandleShape envShape, return true; } -template +template bool Scope::updateEnvShapeIfRequired(JSContext* cx, mozilla::Maybe* envShape, bool needsEnvironment) { @@ -779,18 +681,18 @@ uint32_t LexicalScope::nextFrameSlot(const AbstractScopePtr& scope) { MOZ_CRASH("Not an enclosing intra-frame Scope"); } -template -bool LexicalScope::prepareForScopeCreation( - JSContext* cx, ScopeKind kind, uint32_t firstFrameSlot, - typename MaybeRootedScopeData::MutableHandleType data, - ShapeT envShape) { +template +bool LexicalScope::prepareForScopeCreation(JSContext* cx, ScopeKind kind, + uint32_t firstFrameSlot, + MutableHandle> data, + ShapeType envShape) { bool isNamedLambda = kind == ScopeKind::NamedLambda || kind == ScopeKind::StrictNamedLambda; MOZ_ASSERT_IF(isNamedLambda, firstFrameSlot == LOCALNO_LIMIT); - AbstractBindingIter bi(*data, firstFrameSlot, isNamedLambda); - if (!PrepareScopeData( + BindingIter bi(*data, firstFrameSlot, isNamedLambda); + if (!PrepareScopeData( 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(cx, kind, firstFrameSlot, data, - &envShape)) { + if (!prepareForScopeCreation(cx, kind, firstFrameSlot, data, &envShape)) { return nullptr; } @@ -880,16 +781,14 @@ template LexicalScope::XDR(XDRState* xdr, ScopeKind kind, HandleScope enclosing, MutableHandleScope scope); -template +template bool FunctionScope::prepareForScopeCreation( - JSContext* cx, - typename MaybeRootedScopeData::MutableHandleType data, - bool hasParameterExprs, bool needsEnvironment, HandleFunction fun, - ShapeT envShape) { + JSContext* cx, MutableHandle> data, bool hasParameterExprs, + bool needsEnvironment, HandleFunction fun, ShapeType envShape) { uint32_t firstFrameSlot = 0; - AbstractBindingIter bi(*data, hasParameterExprs); - if (!PrepareScopeData( - cx, bi, data, firstFrameSlot, envShape)) { + BindingIter bi(*data, hasParameterExprs); + if (!PrepareScopeData(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(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 scope, HandleFunction fun, HandleScope enclosing) { @@ -1035,13 +927,24 @@ template FunctionScope::XDR(XDRState* xdr, HandleFunction fun, HandleScope enclosing, MutableHandleScope scope); -template -bool VarScope::prepareForScopeCreation( - JSContext* cx, ScopeKind kind, - typename MaybeRootedScopeData::MutableHandleType data, - uint32_t firstFrameSlot, bool needsEnvironment, ShapeT envShape) { - AbstractBindingIter bi(*data, firstFrameSlot); - if (!PrepareScopeData( +static UniquePtr NewEmptyVarScopeData(JSContext* cx, + uint32_t firstFrameSlot) { + UniquePtr data(NewEmptyScopeData(cx)); + if (data) { + data->nextFrameSlot = firstFrameSlot; + } + + return data; +} + +template +bool VarScope::prepareForScopeCreation(JSContext* cx, ScopeKind kind, + MutableHandle> data, + uint32_t firstFrameSlot, + bool needsEnvironment, + ShapeType envShape) { + BindingIter bi(*data, firstFrameSlot); + if (!PrepareScopeData( 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(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 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> data( - cx, dataArg ? CopyScopeData(cx, dataArg) - : NewEmptyScopeData(cx)); + Rooted> data(cx, dataArg + ? CopyScopeData(cx, dataArg) + : NewEmptyScopeData(cx)); if (!data) { return nullptr; } @@ -1248,15 +1151,14 @@ template WithScope::XDR(XDRState* xdr, HandleScope enclosing, MutableHandleScope scope); -template -bool EvalScope::prepareForScopeCreation( - JSContext* cx, ScopeKind scopeKind, - typename MaybeRootedScopeData::MutableHandleType data, - ShapeT envShape) { +template +bool EvalScope::prepareForScopeCreation(JSContext* cx, ScopeKind scopeKind, + MutableHandle> data, + ShapeType envShape) { if (scopeKind == ScopeKind::StrictEval) { uint32_t firstFrameSlot = 0; - AbstractBindingIter bi(*data, true); - if (!PrepareScopeData( + BindingIter bi(*data, true); + if (!PrepareScopeData( 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(cx, scopeKind, data, &envShape)) { + if (!prepareForScopeCreation(cx, scopeKind, data, &envShape)) { return nullptr; } @@ -1347,14 +1249,14 @@ Zone* ModuleScope::AbstractData::zone() const { } /* static */ -template -bool ModuleScope::prepareForScopeCreation( - JSContext* cx, - typename MaybeRootedScopeData::MutableHandleType data, - HandleModuleObject module, ShapeT envShape) { +template +bool ModuleScope::prepareForScopeCreation(JSContext* cx, + MutableHandle> data, + HandleModuleObject module, + ShapeType envShape) { uint32_t firstFrameSlot = 0; - AbstractBindingIter bi(*data); - if (!PrepareScopeData( + BindingIter bi(*data); + if (!PrepareScopeData( cx, bi, data, firstFrameSlot, envShape)) { return false; } @@ -1377,7 +1279,7 @@ ModuleScope* ModuleScope::createWithData(JSContext* cx, MOZ_ASSERT(enclosing->is()); RootedShape envShape(cx); - if (!prepareForScopeCreation(cx, data, module, &envShape)) { + if (!prepareForScopeCreation(cx, data, module, &envShape)) { return nullptr; } @@ -1487,7 +1389,7 @@ WasmInstanceScope* WasmInstanceScope::create(JSContext* cx, namesCount += globalsCount; Rooted> data( - cx, NewEmptyScopeData(cx, namesCount)); + cx, NewEmptyScopeData(cx, namesCount)); if (!data) { return nullptr; } @@ -1543,7 +1445,7 @@ WasmFunctionScope* WasmFunctionScope::create(JSContext* cx, uint32_t namesCount = locals.length(); Rooted> data( - cx, NewEmptyScopeData(cx, namesCount)); + cx, NewEmptyScopeData(cx, namesCount)); if (!data) { return nullptr; } @@ -1570,10 +1472,9 @@ bool ScopeIter::hasSyntacticEnvironment() const { scope()->kind() != ScopeKind::NonSyntactic; } -AbstractBindingIter::AbstractBindingIter(ScopeKind kind, - BaseScopeData* data, - uint32_t firstFrameSlot) - : BaseAbstractBindingIter() { +BindingIter::BindingIter(ScopeKind kind, BaseScopeData* data, + uint32_t firstFrameSlot) + : Base() { switch (kind) { case ScopeKind::Lexical: case ScopeKind::SimpleCatch: @@ -1623,17 +1524,14 @@ AbstractBindingIter::AbstractBindingIter(ScopeKind kind, } } -AbstractBindingIter::AbstractBindingIter(Scope* scope) - : AbstractBindingIter(scope->kind(), scope->rawData(), - scope->firstFrameSlot()) {} +BindingIter::BindingIter(Scope* scope) + : BindingIter(scope->kind(), scope->rawData(), scope->firstFrameSlot()) {} -AbstractBindingIter::AbstractBindingIter(JSScript* script) - : AbstractBindingIter(script->bodyScope()) {} +BindingIter::BindingIter(JSScript* script) : BindingIter(script->bodyScope()) {} template -void BaseAbstractBindingIter::init( - LexicalScope::AbstractData& data, uint32_t firstFrameSlot, - uint8_t flags) { +void AbstractBindingIter::init(LexicalScope::AbstractData& 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::init( } } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( LexicalScope::AbstractData&, uint32_t, uint8_t); -template void BaseAbstractBindingIter::init( - LexicalScope::AbstractData&, uint32_t, uint8_t); template -void BaseAbstractBindingIter::init( - FunctionScope::AbstractData& data, uint8_t flags) { +void AbstractBindingIter::init(FunctionScope::AbstractData& data, + uint8_t flags) { flags = CanHaveFrameSlots | CanHaveEnvironmentSlots | flags; if (!(flags & HasFormalParameterExprs)) { flags |= CanHaveArgumentSlots; @@ -1679,14 +1575,12 @@ void BaseAbstractBindingIter::init( data.length, flags, 0, JSSLOT_FREE(&CallObject::class_), data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( FunctionScope::AbstractData&, uint8_t); -template void BaseAbstractBindingIter::init( - FunctionScope::AbstractData&, uint8_t); template -void BaseAbstractBindingIter::init(VarScope::AbstractData& data, - uint32_t firstFrameSlot) { +void AbstractBindingIter::init(VarScope::AbstractData& data, + uint32_t firstFrameSlot) { // imports - [0, 0) // positional formals - [0, 0) // other formals - [0, 0) @@ -1698,14 +1592,11 @@ void BaseAbstractBindingIter::init(VarScope::AbstractData& data, JSSLOT_FREE(&VarEnvironmentObject::class_), data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( - VarScope::AbstractData&, uint32_t); -template void BaseAbstractBindingIter::init( - VarScope::AbstractData&, uint32_t); +template void AbstractBindingIter::init(VarScope::AbstractData&, + uint32_t); template -void BaseAbstractBindingIter::init( - GlobalScope::AbstractData& data) { +void AbstractBindingIter::init(GlobalScope::AbstractData& data) { // imports - [0, 0) // positional formals - [0, 0) // other formals - [0, 0) @@ -1715,14 +1606,12 @@ void BaseAbstractBindingIter::init( init(0, 0, 0, data.letStart, data.constStart, CannotHaveSlots, UINT32_MAX, UINT32_MAX, data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( GlobalScope::AbstractData&); -template void BaseAbstractBindingIter::init( - GlobalScope::AbstractData&); template -void BaseAbstractBindingIter::init(EvalScope::AbstractData& data, - bool strict) { +void AbstractBindingIter::init(EvalScope::AbstractData& data, + bool strict) { uint32_t flags; uint32_t firstFrameSlot; uint32_t firstEnvironmentSlot; @@ -1745,14 +1634,11 @@ void BaseAbstractBindingIter::init(EvalScope::AbstractData& data, init(0, 0, 0, data.length, data.length, flags, firstFrameSlot, firstEnvironmentSlot, data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( EvalScope::AbstractData&, bool); -template void BaseAbstractBindingIter::init( - EvalScope::AbstractData&, bool); template -void BaseAbstractBindingIter::init( - ModuleScope::AbstractData& data) { +void AbstractBindingIter::init(ModuleScope::AbstractData& data) { // imports - [0, data.varStart) // positional formals - [data.varStart, data.varStart) // other formals - [data.varStart, data.varStart) @@ -1764,13 +1650,11 @@ void BaseAbstractBindingIter::init( JSSLOT_FREE(&ModuleEnvironmentObject::class_), data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( ModuleScope::AbstractData&); -template void BaseAbstractBindingIter::init( - ModuleScope::AbstractData&); template -void BaseAbstractBindingIter::init( +void AbstractBindingIter::init( WasmInstanceScope::AbstractData& data) { // imports - [0, 0) // positional formals - [0, 0) @@ -1782,13 +1666,11 @@ void BaseAbstractBindingIter::init( CanHaveFrameSlots | CanHaveEnvironmentSlots, UINT32_MAX, UINT32_MAX, data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( WasmInstanceScope::AbstractData&); -template void BaseAbstractBindingIter::init( - WasmInstanceScope::AbstractData&); template -void BaseAbstractBindingIter::init( +void AbstractBindingIter::init( WasmFunctionScope::AbstractData& data) { // imports - [0, 0) // positional formals - [0, 0) @@ -1800,10 +1682,8 @@ void BaseAbstractBindingIter::init( CanHaveFrameSlots | CanHaveEnvironmentSlots, UINT32_MAX, UINT32_MAX, data.trailingNames.start(), data.length); } -template void BaseAbstractBindingIter::init( +template void AbstractBindingIter::init( WasmFunctionScope::AbstractData&); -template void BaseAbstractBindingIter::init( - WasmFunctionScope::AbstractData&); PositionalFormalParameterIter::PositionalFormalParameterIter(Scope* scope) : BindingIter(scope) { @@ -1914,16 +1794,16 @@ JS::ubi::Node::Size JS::ubi::Concrete::size( /* static */ bool ScopeStencil::createForFunctionScope( JSContext* cx, frontend::CompilationInfo& compilationInfo, - ParserFunctionScopeData* data, bool hasParameterExprs, + Handle dataArg, bool hasParameterExprs, bool needsEnvironment, FunctionIndex functionIndex, bool isArrow, mozilla::Maybe enclosing, ScopeIndex* index) { - // If incoming data is null, initialize an epty scope data. + // 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> data( + cx, dataArg ? CopyScopeData(cx, dataArg) + : NewEmptyScopeData(cx)); if (!data) { - data = NewEmptyScopeData(cx) - .release(); - if (!data) { - return false; - } + return false; } // We do not initialize the canonical function while the data is owned by the @@ -1932,77 +1812,77 @@ bool ScopeStencil::createForFunctionScope( uint32_t firstFrameSlot = 0; mozilla::Maybe envShape; - if (!FunctionScope::prepareForScopeCreation( + 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 dataArg, uint32_t firstFrameSlot, mozilla::Maybe enclosing, ScopeIndex* index) { - // If incoming data is null, initialize an epty scope data. + // 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> data( + cx, CopyScopeData(cx, dataArg)); if (!data) { - data = NewEmptyScopeData(cx) - .release(); - if (!data) { - return false; - } + return false; } mozilla::Maybe envShape; - if (!LexicalScope::prepareForScopeCreation( - 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 enclosing, ScopeIndex* index) { - // If incoming data is null, initialize an epty scope data. + Handle dataArg, uint32_t firstFrameSlot, + bool needsEnvironment, mozilla::Maybe 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> data( + cx, dataArg ? CopyScopeData(cx, dataArg) + : NewEmptyVarScopeData(cx, firstFrameSlot)); if (!data) { - data = - NewEmptyScopeData(cx).release(); - if (!data) { - return false; - } + return false; } mozilla::Maybe envShape; - if (!VarScope::prepareForScopeCreation( - 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. + Handle 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> data( + cx, dataArg ? CopyScopeData(cx, dataArg) + : NewEmptyScopeData(cx)); if (!data) { - data = NewEmptyScopeData(cx) - .release(); - if (!data) { - return false; - } + return false; } // The global scope has no environment shape. Its environment is the @@ -2016,47 +1896,46 @@ 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 enclosing, + Handle dataArg, mozilla::Maybe enclosing, ScopeIndex* index) { - // If incoming data is null, initialize an epty scope data. + // 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> data( + cx, dataArg ? CopyScopeData(cx, dataArg) + : NewEmptyScopeData(cx)); if (!data) { - data = - NewEmptyScopeData(cx).release(); - if (!data) { - return false; - } + return false; } uint32_t firstFrameSlot = 0; mozilla::Maybe envShape; - if (!EvalScope::prepareForScopeCreation(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 enclosing, + Handle dataArg, mozilla::Maybe enclosing, ScopeIndex* index) { - // If incoming data is null, initialize an epty scope data. + // 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> data( + cx, dataArg ? CopyScopeData(cx, dataArg) + : NewEmptyScopeData(cx)); if (!data) { - data = NewEmptyScopeData(cx) - .release(); - if (!data) { - return false; - } + 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 envShape; - if (!ModuleScope::prepareForScopeCreation(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 +template 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 -UniquePtr ScopeStencil::createSpecificScopeData( - JSContext* cx, CompilationInfo& compilationInfo) { - return LiftParserScopeData(cx, &data()); +template +UniquePtr ScopeStencil::releaseData( + CompilationInfo& compilationInfo) { + return UniquePtr( + static_cast(data_.release())); } template <> -UniquePtr -ScopeStencil::createSpecificScopeData( - JSContext* cx, CompilationInfo& compilationInfo) { - // Allocate a new vm function-scope. - UniquePtr data = - LiftParserScopeData(cx, &this->data()); - if (!data) { - return nullptr; - } +UniquePtr ScopeStencil::releaseData( + CompilationInfo& compilationInfo) { + // Initialize the GCPtrs in the Scope::Data. + data().canonicalFunction = + compilationInfo.functions[*functionIndex_]; - // Initialize the GCPtrs in the FunctionScope::Data. - data->canonicalFunction = compilationInfo.functions[*functionIndex_]; - - return data; + return UniquePtr( + static_cast(data_.release())); } template <> -UniquePtr ScopeStencil::createSpecificScopeData( - JSContext* cx, CompilationInfo& compilationInfo) { - // Allocate a new vm module-scope. - UniquePtr data = - LiftParserScopeData(cx, &this->data()); - if (!data) { - return nullptr; - } +UniquePtr ScopeStencil::releaseData( + CompilationInfo& compilationInfo) { + // Initialize the GCPtrs in the Scope::Data. + data().module = compilationInfo.module; - // Initialize the GCPtrs in the ModuleScope::Data. - data->module = compilationInfo.module; - - return data; + return UniquePtr( + static_cast(data_.release())); } // WithScope does not use binding data. @@ -2165,10 +2033,7 @@ template <> Scope* ScopeStencil::createSpecificScope( JSContext* cx, CompilationInfo& compilationInfo) { Rooted> rootedData( - cx, createSpecificScopeData(cx, compilationInfo)); - if (!rootedData) { - return nullptr; - } + cx, releaseData(compilationInfo)); MOZ_ASSERT(enclosing(compilationInfo).isNullptr()); @@ -2176,17 +2041,14 @@ Scope* ScopeStencil::createSpecificScope( return Scope::create(cx, kind(), nullptr, nullptr, &rootedData); } -template +template Scope* ScopeStencil::createSpecificScope(JSContext* cx, CompilationInfo& compilationInfo) { - Rooted> rootedData( - cx, createSpecificScopeData(cx, compilationInfo)); - if (!rootedData) { - return nullptr; - } + Rooted> rootedData( + cx, releaseData(compilationInfo)); RootedShape shape(cx); - if (!createSpecificShape( + if (!createSpecificShape( cx, kind(), rootedData.get().get(), &shape)) { return nullptr; } @@ -2194,8 +2056,8 @@ 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(cx, kind(), enclosingScope, shape, - &rootedData); + return Scope::create(cx, kind(), enclosingScope, shape, + &rootedData); } template Scope* ScopeStencil::createSpecificScope( diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h index 2427426b16c5..b090febd879c 100644 --- a/js/src/vm/Scope.h +++ b/js/src/vm/Scope.h @@ -26,23 +26,17 @@ namespace js { namespace frontend { -struct CompilationInfo; class ScriptStencil; class ScopeStencil; -class ParserAtom; }; // namespace frontend template class AbstractBaseScopeData; -template -class BaseAbstractBindingIter; - template class AbstractBindingIter; -using BindingIter = AbstractBindingIter; - +class BindingIter; class ModuleObject; class AbstractScopePtr; @@ -78,9 +72,6 @@ const char* ScopeKindString(ScopeKind kind); template class AbstractBindingName { - template - 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 - AbstractBindingName(NameT* name, const AbstractBindingName& 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 - AbstractBindingName transformName(NewNameT* newName) const { - return AbstractBindingName(newName, *this); - } - private: - friend class BaseAbstractBindingIter; + friend class AbstractBindingIter; 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 -class alignas(ScopeDataAlignBytes) AbstractBaseScopeData { - public: - using NameType = NameT; -}; +class alignas(ScopeDataAlignBytes) AbstractBaseScopeData {}; using BaseScopeData = AbstractBaseScopeData; @@ -175,7 +154,7 @@ using BaseScopeData = AbstractBaseScopeData; * * The names array is implemented in terms of an generic type that * allows specialization between a (JSAtom*) BindingName and a - * ParserAtom + * ParserAtomId */ template class AbstractTrailingNamesArray { @@ -298,7 +277,7 @@ class WrappedPtrOperations { class Scope : public gc::TenuredCellWithNonGCPointer { friend class GCMarker; friend class frontend::ScopeStencil; - friend class js::AbstractBindingIter; + friend class js::BindingIter; protected: // The raw data pointer, stored in the cell header. @@ -337,11 +316,11 @@ class Scope : public gc::TenuredCellWithNonGCPointer { template void applyScopeDataTyped(F&& f); - template + template static bool updateEnvShapeIfRequired(JSContext* cx, MutableHandleShape shape, bool needsEnvironment); - template + template static bool updateEnvShapeIfRequired(JSContext* cx, mozilla::Maybe* envShape, bool needsEnvironment); @@ -433,25 +412,14 @@ class Scope : public gc::TenuredCellWithNonGCPointer { }; template -inline size_t SizeOfScopeData(uint32_t numBindings) { - return sizeof(Data) + ((numBindings ? numBindings - 1 : 0) * - sizeof(AbstractBindingName)); +inline size_t SizeOfData(uint32_t numBindings) { + static_assert(std::is_base_of_v, + "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 -using AbstractScopeData = typename ScopeT::template AbstractData; - -template -using MaybeRootedScopeData = std::conditional_t< - std::is_same_v, - MaybeRooted, AllowGC::CanGC>, - MaybeRooted*, 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; + friend class BindingIter; friend class GCMarker; friend class frontend::ScopeStencil; @@ -516,12 +484,11 @@ class LexicalScope : public Scope { uint32_t firstFrameSlot, HandleScope enclosing); - template - static bool prepareForScopeCreation( - JSContext* cx, ScopeKind kind, uint32_t firstFrameSlot, - typename MaybeRootedScopeData::MutableHandleType - data, - ShapeT envShape); + template + static bool prepareForScopeCreation(JSContext* cx, ScopeKind kind, + uint32_t firstFrameSlot, + MutableHandle> data, + ShapeType envShape); Data& data() { return *static_cast(rawData()); } const Data& data() const { return *static_cast(rawData()); } @@ -564,7 +531,7 @@ inline bool Scope::is() const { // class FunctionScope : public Scope { friend class GCMarker; - friend class AbstractBindingIter; + friend class BindingIter; friend class PositionalFormalParameterIter; friend class Scope; friend class AbstractScopePtr; @@ -630,13 +597,12 @@ class FunctionScope : public Scope { using Data = AbstractData; - template - static bool prepareForScopeCreation( - JSContext* cx, - typename MaybeRootedScopeData::MutableHandleType - data, - bool hasParameterExprs, bool needsEnvironment, HandleFunction fun, - ShapeT envShape); + template + static bool prepareForScopeCreation(JSContext* cx, + MutableHandle> data, + bool hasParameterExprs, + bool needsEnvironment, HandleFunction fun, + ShapeType envShape); static FunctionScope* clone(JSContext* cx, Handle 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; + 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 - static bool prepareForScopeCreation( - JSContext* cx, ScopeKind kind, - typename MaybeRootedScopeData::MutableHandleType data, - uint32_t firstFrameSlot, bool needsEnvironment, ShapeT envShape); + template + static bool prepareForScopeCreation(JSContext* cx, ScopeKind kind, + MutableHandle> data, + uint32_t firstFrameSlot, + bool needsEnvironment, + ShapeType envShape); Data& data() { return *static_cast(rawData()); } @@ -763,14 +729,14 @@ inline bool Scope::is() const { // class GlobalScope : public Scope { friend class Scope; - friend class AbstractBindingIter; + friend class BindingIter; friend class GCMarker; public: // Data is public because it is created by the frontend. See // Parser::newGlobalScopeData. template - struct AbstractData : public AbstractBaseScopeData { + 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; + friend class BindingIter; friend class GCMarker; friend class frontend::ScopeStencil; @@ -896,11 +862,10 @@ class EvalScope : public Scope { MutableHandle> data, HandleScope enclosing); - template - static bool prepareForScopeCreation( - JSContext* cx, ScopeKind scopeKind, - typename MaybeRootedScopeData::MutableHandleType data, - ShapeT envShape); + template + static bool prepareForScopeCreation(JSContext* cx, ScopeKind scopeKind, + MutableHandle> data, + ShapeType envShape); Data& data() { return *static_cast(rawData()); } @@ -940,7 +905,7 @@ inline bool Scope::is() const { // class ModuleScope : public Scope { friend class GCMarker; - friend class AbstractBindingIter; + 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::newModuleScopeData. template - struct AbstractData : public AbstractBaseScopeData { + struct AbstractData : BaseScopeData { // The module of the scope. GCPtr module = {}; @@ -989,11 +954,11 @@ class ModuleScope : public Scope { MutableHandle> data, Handle module, HandleScope enclosing); - template - static bool prepareForScopeCreation( - JSContext* cx, - typename MaybeRootedScopeData::MutableHandleType data, - HandleModuleObject module, ShapeT envShape); + template + static bool prepareForScopeCreation(JSContext* cx, + MutableHandle> data, + HandleModuleObject module, + ShapeType envShape); Data& data() { return *static_cast(rawData()); } @@ -1006,7 +971,7 @@ class ModuleScope : public Scope { }; class WasmInstanceScope : public Scope { - friend class AbstractBindingIter; + 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; + friend class BindingIter; friend class Scope; friend class GCMarker; friend class AbstractScopePtr; @@ -1152,7 +1117,7 @@ void Scope::applyScopeDataTyped(F&& f) { // } // template -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& data, - uint32_t firstFrameSlot, bool isNamedLambda) { + AbstractBindingIter(LexicalScope::AbstractData& data, + uint32_t firstFrameSlot, bool isNamedLambda) { init(data, firstFrameSlot, isNamedLambda ? IsNamedLambda : 0); } - BaseAbstractBindingIter(FunctionScope::AbstractData& data, - bool hasParameterExprs) { + AbstractBindingIter(FunctionScope::AbstractData& data, + bool hasParameterExprs) { init(data, IgnoreDestructuredFormalParameters | (hasParameterExprs ? HasFormalParameterExprs : 0)); } - BaseAbstractBindingIter(VarScope::AbstractData& data, - uint32_t firstFrameSlot) { + AbstractBindingIter(VarScope::AbstractData& data, + uint32_t firstFrameSlot) { init(data, firstFrameSlot); } - explicit BaseAbstractBindingIter(GlobalScope::AbstractData& data) { + explicit AbstractBindingIter(GlobalScope::AbstractData& data) { init(data); } - explicit BaseAbstractBindingIter(ModuleScope::AbstractData& data) { + explicit AbstractBindingIter(ModuleScope::AbstractData& data) { init(data); } - explicit BaseAbstractBindingIter( - WasmFunctionScope::AbstractData& data) { + explicit AbstractBindingIter(WasmFunctionScope::AbstractData& data) { init(data); } - BaseAbstractBindingIter(EvalScope::AbstractData& data, bool strict) { + AbstractBindingIter(EvalScope::AbstractData& data, bool strict) { init(data, strict); } - MOZ_IMPLICIT BaseAbstractBindingIter( - const BaseAbstractBindingIter& bi) = default; + MOZ_IMPLICIT AbstractBindingIter(const AbstractBindingIter& bi) = + default; bool done() const { return index_ == length_; } @@ -1444,34 +1408,22 @@ class BaseAbstractBindingIter { } }; -template -class AbstractBindingIter; - -template <> -class AbstractBindingIter : public BaseAbstractBindingIter { - using Base = BaseAbstractBindingIter; +class BindingIter : public AbstractBindingIter { + using Base = AbstractBindingIter; public: - AbstractBindingIter(ScopeKind kind, BaseScopeData* data, - uint32_t firstFrameSlot); + BindingIter(ScopeKind kind, BaseScopeData* data, uint32_t firstFrameSlot); - explicit AbstractBindingIter(Scope* scope); - explicit AbstractBindingIter(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 - : public BaseAbstractBindingIter { - using Base = BaseAbstractBindingIter; - - 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& bi, - const JSClass* cls, uint32_t numSlots, uint32_t baseShapeFlags); - Shape* EmptyEnvironmentShape(JSContext* cx, const JSClass* cls, uint32_t numSlots, uint32_t baseShapeFlags); diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 1021bd471044..188979b18155 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -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)); diff --git a/js/src/vm/SelfHosting.h b/js/src/vm/SelfHosting.h index d97c54040ca0..229a8cc1782d 100644 --- a/js/src/vm/SelfHosting.h +++ b/js/src/vm/SelfHosting.h @@ -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); diff --git a/js/src/vm/StringType.cpp b/js/src/vm/StringType.cpp index f92f689e4169..80757131ecf8 100644 --- a/js/src/vm/StringType.cpp +++ b/js/src/vm/StringType.cpp @@ -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); diff --git a/js/src/vm/StringType.h b/js/src/vm/StringType.h index c68bf0665744..2a43d1b82744 100644 --- a/js/src/vm/StringType.h +++ b/js/src/vm/StringType.h @@ -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. diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index 4fb5dd37a56c..23b14c032408 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -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().label(); } -static inline const ParserName* LabeledStatementLabel(ParseNode* pn) { +static inline PropertyName* LabeledStatementLabel(ParseNode* pn) { return pn->as().label(); } @@ -565,8 +565,8 @@ static ParseNode* DotBase(ParseNode* pn) { return &pn->as().expression(); } -static const ParserName* DotMember(ParseNode* pn) { - return pn->as().name(); +static PropertyName* DotMember(ParseNode* pn) { + return &pn->as().name(); } static ParseNode* ElemBase(ParseNode* pn) { @@ -577,9 +577,9 @@ static ParseNode* ElemIndex(ParseNode* pn) { return &pn->as().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().atom()->asName(); + return BinaryLeft(pn)->as().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; using FuncImportMap = HashMap; - using GlobalMap = HashMap; - using MathNameMap = HashMap; + using GlobalMap = HashMap; + using MathNameMap = HashMap; using ArrayViewVector = Vector; 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::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& parser_; public: - ModuleValidator(JSContext* cx, CompilationInfo& compilationInfo, - AsmJSParser& parser, FunctionNode* moduleFunctionNode) - : ModuleValidatorShared(cx, compilationInfo, moduleFunctionNode), - parser_(parser) {} + ModuleValidator(JSContext* cx, AsmJSParser& 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_(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 LabelVector; +typedef Vector LabelVector; class MOZ_STACK_CLASS FunctionValidatorShared { public: @@ -2324,8 +2316,8 @@ class MOZ_STACK_CLASS FunctionValidatorShared { }; protected: - using LocalMap = HashMap; - using LabelMap = HashMap; + using LocalMap = HashMap; + using LabelMap = HashMap; // This is also a ModuleValidator& 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().name(); + PropertyName* argName = arg->as().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().name(); + PropertyName* globalName = ctorExpr->as().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().name(); + PropertyName* varName = var->as().name(); if (!CheckModuleLevelName(m, var, varName)) { return false; } @@ -3119,7 +3109,7 @@ static bool CheckModuleGlobals(ModuleValidator& 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().name(); + PropertyName* name = var->as().name(); if (!CheckIdentifier(f.m(), var, name)) { return false; @@ -3345,7 +3335,7 @@ static bool CheckNumericLiteral(FunctionValidator& f, ParseNode* num, static bool CheckVarRef(FunctionValidatorShared& f, ParseNode* varRef, Type* type) { - const ParserName* name = varRef->as().name(); + PropertyName* name = varRef->as().name(); if (const FunctionValidatorShared::Local* local = f.lookupLocal(name)) { if (!f.encoder().writeOp(Op::GetLocal)) { @@ -3661,7 +3651,7 @@ static bool CheckStoreArray(FunctionValidator& f, ParseNode* lhs, template static bool CheckAssignName(FunctionValidator& f, ParseNode* lhs, ParseNode* rhs, Type* type) { - const ParserName* name = lhs->as().name(); + RootedPropertyName name(f.cx(), lhs->as().name()); if (const FunctionValidatorShared::Local* lhsVar = f.lookupLocal(name)) { Type rhsType; @@ -3943,7 +3933,7 @@ static bool CheckSignatureAgainstExisting(ModuleValidatorShared& m, template static bool CheckFunctionSignature(ModuleValidator& 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 static bool CheckInternalCall(FunctionValidator& 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& f, ParseNode* callNode, template static bool CheckFuncPtrTableAgainstExisting(ModuleValidator& 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& f, ParseNode* callNode, return f.fail(tableNode, "expecting name of function-pointer array"); } - const ParserName* name = tableNode->as().name(); + PropertyName* name = tableNode->as().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& f, ParseNode* callNode, unsigned ffiIndex, Type ret, Type* type) { MOZ_ASSERT(ret.isCanonical()); - const ParserName* calleeName = CallCallee(callNode)->as().name(); + PropertyName* calleeName = CallCallee(callNode)->as().name(); if (ret.isFloat()) { return f.fail(callNode, "FFI calls can't return float"); @@ -4511,7 +4500,7 @@ static bool CheckCoercedCall(FunctionValidator& f, ParseNode* call, return f.fail(callee, "unexpected callee expression type"); } - const ParserName* calleeName = callee->as().name(); + PropertyName* calleeName = callee->as().name(); if (const ModuleValidatorShared::Global* global = f.lookupGlobal(calleeName)) { @@ -5939,7 +5928,7 @@ static bool CheckLexicalScope(FunctionValidator& 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& 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& m, ParseNode* decl) { elem, "function-pointer table's elements must be names of functions"); } - const ParserName* funcName = elem->as().name(); + PropertyName* funcName = elem->as().name(); const ModuleValidatorShared::Func* func = m.lookupFuncDef(funcName); if (!func) { return m.fail( @@ -6264,14 +6253,13 @@ static bool CheckFuncPtrTables(ModuleValidator& 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().name(); + PropertyName* funcName = pn->as().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& m) { } template -static SharedModule CheckModule(JSContext* cx, CompilationInfo& compilationInfo, - AsmJSParser& parser, ParseNode* stmtList, - unsigned* time) { +static SharedModule CheckModule(JSContext* cx, AsmJSParser& parser, + ParseNode* stmtList, unsigned* time) { int64_t before = PRMJ_Now(); FunctionNode* moduleFunctionNode = parser.pc_->functionBox()->functionNode; - ModuleValidator m(cx, compilationInfo, parser, moduleFunctionNode); + ModuleValidator m(cx, parser, moduleFunctionNode); if (!m.init()) { return nullptr; } @@ -7058,9 +7045,8 @@ static bool EstablishPreconditions(JSContext* cx, } template -static bool DoCompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo, - AsmJSParser& parser, ParseNode* stmtList, - bool* validated) { +static bool DoCompileAsmJS(JSContext* cx, AsmJSParser& 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& parser, ParseNode* stmtList, - bool* validated) { - return DoCompileAsmJS(cx, compilationInfo, parser, stmtList, validated); +bool js::CompileAsmJS(JSContext* cx, AsmJSParser& parser, + ParseNode* stmtList, bool* validated) { + return DoCompileAsmJS(cx, parser, stmtList, validated); } -bool js::CompileAsmJS(JSContext* cx, CompilationInfo& compilationInfo, - AsmJSParser& parser, ParseNode* stmtList, - bool* validated) { - return DoCompileAsmJS(cx, compilationInfo, parser, stmtList, validated); +bool js::CompileAsmJS(JSContext* cx, AsmJSParser& parser, + ParseNode* stmtList, bool* validated) { + return DoCompileAsmJS(cx, parser, stmtList, validated); } /*****************************************************************************/ diff --git a/js/src/wasm/AsmJS.h b/js/src/wasm/AsmJS.h index 76db8799b965..6ca84cd4a377 100644 --- a/js/src/wasm/AsmJS.h +++ b/js/src/wasm/AsmJS.h @@ -43,8 +43,6 @@ namespace js { namespace frontend { -struct CompilationInfo; - class ParseContext; class ParseNode; @@ -64,15 +62,15 @@ using AsmJSParser = frontend::Parser; // indeterminate amount and the entire function should be reparsed from the // beginning. -extern MOZ_MUST_USE bool CompileAsmJS( - JSContext* cx, frontend::CompilationInfo& compilationInfo, - AsmJSParser& parser, frontend::ParseNode* stmtList, - bool* validated); +extern MOZ_MUST_USE bool CompileAsmJS(JSContext* cx, + AsmJSParser& parser, + frontend::ParseNode* stmtList, + bool* validated); -extern MOZ_MUST_USE bool CompileAsmJS( - JSContext* cx, frontend::CompilationInfo& compilationInfo, - AsmJSParser& parser, frontend::ParseNode* stmtList, - bool* validated); +extern MOZ_MUST_USE bool CompileAsmJS(JSContext* cx, + AsmJSParser& parser, + frontend::ParseNode* stmtList, + bool* validated); // asm.js module/export queries: