From f0828bc714992a1eb3b34069d995e03c6e329038 Mon Sep 17 00:00:00 2001 From: Matthew Gaudet Date: Wed, 17 May 2023 14:59:51 +0000 Subject: [PATCH] Bug 1833484 - Optimize bytecode emission for Infinity, NaN and undefined where possible. r=arai This is possible because once we are looking at the global we know that these values aren't configurable and therefore have well known values. Differential Revision: https://phabricator.services.mozilla.com/D178243 --- js/public/Value.h | 5 +++++ js/src/frontend/NameOpEmitter.cpp | 23 ++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/js/public/Value.h b/js/public/Value.h index e3579da8e99e..de8db0fed860 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -463,6 +463,11 @@ static MOZ_ALWAYS_INLINE double GenericNaN() { return mozilla::BitwiseCast(detail::CanonicalizedNaNBits); } +// Return the infinity the engine uses +static MOZ_ALWAYS_INLINE double Infinity() { + return mozilla::BitwiseCast(detail::InfinityBits); +} + // Convert an arbitrary double to one compatible with JS::Value representation // by replacing any NaN value with a canonical one. static MOZ_ALWAYS_INLINE double CanonicalizeNaN(double d) { diff --git a/js/src/frontend/NameOpEmitter.cpp b/js/src/frontend/NameOpEmitter.cpp index 074aaabf6d86..f36c7a2028b7 100644 --- a/js/src/frontend/NameOpEmitter.cpp +++ b/js/src/frontend/NameOpEmitter.cpp @@ -12,6 +12,7 @@ #include "frontend/SharedContext.h" #include "frontend/TDZCheckCache.h" #include "frontend/ValueUsage.h" +#include "js/Value.h" #include "vm/Opcodes.h" using namespace js; @@ -44,9 +45,25 @@ bool NameOpEmitter::emitGet() { return false; } } else { - if (!bce_->emitAtomOp(JSOp::GetGName, name_)) { - // [stack] VAL - return false; + // Some names on the global are not configurable and have fixed values + // which we can emit instead. + if (name_ == TaggedParserAtomIndex::WellKnown::undefined()) { + if (!bce_->emit1(JSOp::Undefined)) { + return false; + } + } else if (name_ == TaggedParserAtomIndex::WellKnown::NaN()) { + if (!bce_->emitDouble(JS::GenericNaN())) { + return false; + } + } else if (name_ == TaggedParserAtomIndex::WellKnown::Infinity()) { + if (!bce_->emitDouble(JS::Infinity())) { + return false; + } + } else { + if (!bce_->emitAtomOp(JSOp::GetGName, name_)) { + // [stack] VAL + return false; + } } } break;