diff options
Diffstat (limited to 'js/src/frontend')
-rw-r--r-- | js/src/frontend/BytecodeEmitter.cpp | 114 | ||||
-rw-r--r-- | js/src/frontend/BytecodeEmitter.h | 2 | ||||
-rw-r--r-- | js/src/frontend/Stencil.cpp | 2 | ||||
-rw-r--r-- | js/src/frontend/Stencil.h | 21 | ||||
-rw-r--r-- | js/src/frontend/StencilXdr.cpp | 2 |
5 files changed, 126 insertions, 15 deletions
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 2759fa5924..f288d333e1 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -72,6 +72,7 @@ #include "vm/Scope.h" // GetScopeDataTrailingNames #include "vm/SharedStencil.h" // ScopeNote #include "vm/ThrowMsgKind.h" // ThrowMsgKind +#include "vm/TypeofEqOperand.h" // TypeofEqOperand using namespace js; using namespace js::frontend; @@ -11499,6 +11500,101 @@ bool BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) { return emit1(op); } +bool BytecodeEmitter::tryEmitTypeofEq(ListNode* node, bool* emitted) { + // Emit specialized opcode for `typeof val == "type` or `typeof val != "type` + // if possible. + // + // NOTE: Given the comparison is done for string, `==` and `===` have + // no difference. Same for `!=` and `!==`. + MOZ_ASSERT(node->isKind(ParseNodeKind::StrictEqExpr) || + node->isKind(ParseNodeKind::EqExpr) || + node->isKind(ParseNodeKind::StrictNeExpr) || + node->isKind(ParseNodeKind::NeExpr)); + + if (node->count() != 2) { + *emitted = false; + return true; + } + + ParseNode* left = node->head(); + ParseNode* right = left->pn_next; + MOZ_ASSERT(right); + + UnaryNode* typeofNode; + NameNode* typenameNode; + JSOp op; + + if (node->isKind(ParseNodeKind::StrictEqExpr) || + node->isKind(ParseNodeKind::EqExpr)) { + op = JSOp::Eq; + } else { + op = JSOp::Ne; + } + + // NOTE: ParseNodeKind::TypeOfExpr cannot use JSOp::TypeofEq. + // See JSOp::GetName document. + if (left->isKind(ParseNodeKind::TypeOfNameExpr) && + right->isKind(ParseNodeKind::StringExpr)) { + typeofNode = &left->as<UnaryNode>(); + typenameNode = &right->as<NameNode>(); + } else if (right->isKind(ParseNodeKind::TypeOfNameExpr) && + left->isKind(ParseNodeKind::StringExpr)) { + typeofNode = &right->as<UnaryNode>(); + typenameNode = &left->as<NameNode>(); + } else { + *emitted = false; + return true; + } + + JSType type; + TaggedParserAtomIndex typeName = typenameNode->atom(); + if (typeName == TaggedParserAtomIndex::WellKnown::undefined()) { + type = JSTYPE_UNDEFINED; + } else if (typeName == TaggedParserAtomIndex::WellKnown::object()) { + type = JSTYPE_OBJECT; + } else if (typeName == TaggedParserAtomIndex::WellKnown::function()) { + type = JSTYPE_FUNCTION; + } else if (typeName == TaggedParserAtomIndex::WellKnown::string()) { + type = JSTYPE_STRING; + } else if (typeName == TaggedParserAtomIndex::WellKnown::number()) { + type = JSTYPE_NUMBER; + } else if (typeName == TaggedParserAtomIndex::WellKnown::boolean()) { + type = JSTYPE_BOOLEAN; + } else if (typeName == TaggedParserAtomIndex::WellKnown::symbol()) { + type = JSTYPE_SYMBOL; + } else if (typeName == TaggedParserAtomIndex::WellKnown::bigint()) { + type = JSTYPE_BIGINT; + } +#ifdef ENABLE_RECORD_TUPLE + else if (typeName == TaggedParserAtomIndex::WellKnown::record()) { + type = JSTYPE_RECORD; + } else if (typeName == TaggedParserAtomIndex::WellKnown::tuple()) { + type = JSTYPE_TUPLE; + } +#endif + else { + *emitted = false; + return true; + } + + if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) { + return false; + } + + if (!emitTree(typeofNode->kid())) { + // [stack] VAL + return false; + } + + if (!emit2(JSOp::TypeofEq, TypeofEqOperand(type, op).rawValue())) { + // [stack] CMP + return false; + } + + *emitted = true; + return true; +} + bool BytecodeEmitter::emitFunctionFormalParameters(ParamsBodyNode* paramsBody) { FunctionBox* funbox = sc->asFunctionBox(); @@ -12394,15 +12490,25 @@ bool BytecodeEmitter::emitTree( } break; + case ParseNodeKind::StrictEqExpr: + case ParseNodeKind::EqExpr: + case ParseNodeKind::StrictNeExpr: + case ParseNodeKind::NeExpr: { + bool emitted; + if (!tryEmitTypeofEq(&pn->as<ListNode>(), &emitted)) { + return false; + } + if (emitted) { + return true; + } + } + [[fallthrough]]; + case ParseNodeKind::AddExpr: case ParseNodeKind::SubExpr: case ParseNodeKind::BitOrExpr: case ParseNodeKind::BitXorExpr: case ParseNodeKind::BitAndExpr: - case ParseNodeKind::StrictEqExpr: - case ParseNodeKind::EqExpr: - case ParseNodeKind::StrictNeExpr: - case ParseNodeKind::NeExpr: case ParseNodeKind::LtExpr: case ParseNodeKind::LeExpr: case ParseNodeKind::GtExpr: diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 251797d1f7..a0e58d629f 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -925,6 +925,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter { // |op| must be JSOp::Typeof or JSOp::TypeofExpr. [[nodiscard]] bool emitTypeof(UnaryNode* typeofNode, JSOp op); + [[nodiscard]] bool tryEmitTypeofEq(ListNode* node, bool* emitted); + [[nodiscard]] bool emitUnary(UnaryNode* unaryNode); [[nodiscard]] bool emitRightAssociative(ListNode* node); [[nodiscard]] bool emitLeftAssociative(ListNode* node); diff --git a/js/src/frontend/Stencil.cpp b/js/src/frontend/Stencil.cpp index 67ed2a90ca..447a83f595 100644 --- a/js/src/frontend/Stencil.cpp +++ b/js/src/frontend/Stencil.cpp @@ -2783,6 +2783,8 @@ JSScript* CompilationStencil::instantiateSelfHostedTopLevelForRealm( JSFunction* CompilationStencil::instantiateSelfHostedLazyFunction( JSContext* cx, CompilationAtomCache& atomCache, ScriptIndex index, Handle<JSAtom*> name) { + MOZ_ASSERT(cx->zone()->suppressAllocationMetadataBuilder); + GeneratorKind generatorKind = scriptExtra[index].immutableFlags.hasFlag( ImmutableScriptFlagsEnum::IsGenerator) ? GeneratorKind::Generator diff --git a/js/src/frontend/Stencil.h b/js/src/frontend/Stencil.h index 91308ffcc9..b5baa8e6c4 100644 --- a/js/src/frontend/Stencil.h +++ b/js/src/frontend/Stencil.h @@ -502,13 +502,14 @@ class ScopeStencil { } }; -class StencilModuleAssertion { +class StencilModuleImportAttribute { public: TaggedParserAtomIndex key; TaggedParserAtomIndex value; - StencilModuleAssertion() = default; - StencilModuleAssertion(TaggedParserAtomIndex key, TaggedParserAtomIndex value) + StencilModuleImportAttribute() = default; + StencilModuleImportAttribute(TaggedParserAtomIndex key, + TaggedParserAtomIndex value) : key(key), value(value) {} }; @@ -516,9 +517,9 @@ class StencilModuleRequest { public: TaggedParserAtomIndex specifier; - using AssertionVector = - Vector<StencilModuleAssertion, 0, js::SystemAllocPolicy>; - AssertionVector assertions; + using ImportAttributeVector = + Vector<StencilModuleImportAttribute, 0, js::SystemAllocPolicy>; + ImportAttributeVector attributes; // For XDR only. StencilModuleRequest() = default; @@ -531,23 +532,23 @@ class StencilModuleRequest { StencilModuleRequest(const StencilModuleRequest& other) : specifier(other.specifier) { AutoEnterOOMUnsafeRegion oomUnsafe; - if (!assertions.appendAll(other.assertions)) { + if (!attributes.appendAll(other.attributes)) { oomUnsafe.crash("StencilModuleRequest::StencilModuleRequest"); } } StencilModuleRequest(StencilModuleRequest&& other) noexcept - : specifier(other.specifier), assertions(std::move(other.assertions)) {} + : specifier(other.specifier), attributes(std::move(other.attributes)) {} StencilModuleRequest& operator=(StencilModuleRequest& other) { specifier = other.specifier; - assertions = std::move(other.assertions); + attributes = std::move(other.attributes); return *this; } StencilModuleRequest& operator=(StencilModuleRequest&& other) noexcept { specifier = other.specifier; - assertions = std::move(other.assertions); + attributes = std::move(other.attributes); return *this; } }; diff --git a/js/src/frontend/StencilXdr.cpp b/js/src/frontend/StencilXdr.cpp index 1146d023d4..ca65b905e2 100644 --- a/js/src/frontend/StencilXdr.cpp +++ b/js/src/frontend/StencilXdr.cpp @@ -577,7 +577,7 @@ template <XDRMode mode> /* static */ XDRResult StencilXDR::codeModuleRequest( XDRState<mode>* xdr, StencilModuleRequest& stencil) { MOZ_TRY(xdr->codeUint32(stencil.specifier.rawDataRef())); - MOZ_TRY(XDRVectorContent(xdr, stencil.assertions)); + MOZ_TRY(XDRVectorContent(xdr, stencil.attributes)); return Ok(); } |