summaryrefslogtreecommitdiffstats
path: root/js/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend')
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp114
-rw-r--r--js/src/frontend/BytecodeEmitter.h2
-rw-r--r--js/src/frontend/Stencil.cpp2
-rw-r--r--js/src/frontend/Stencil.h21
-rw-r--r--js/src/frontend/StencilXdr.cpp2
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();
}