summaryrefslogtreecommitdiffstats
path: root/js/src/frontend/BytecodeEmitter.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /js/src/frontend/BytecodeEmitter.cpp
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/frontend/BytecodeEmitter.cpp')
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp114
1 files changed, 110 insertions, 4 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: