Bug 1548908: Remove "well-known numbers" from JSRuntime r=tcampbell
authorIain Ireland <iireland@mozilla.com>
Mon, 03 Jun 2019 15:59:25 +0000
changeset 538173 2953a85f6b5f5dd6f3820129b9394ead251369e8
parent 538172 f42ce0774d43f0361b30b255bbffdf63e940bcd6
child 538174 411b7238682916ba85768dc0d872ac417fb4ba65
push id11522
push userffxbld-merge
push dateMon, 01 Jul 2019 09:00:55 +0000
treeherdermozilla-beta@53ea74d2bd09 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1548908
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1548908: Remove "well-known numbers" from JSRuntime r=tcampbell Back when we first freed the lizard in 1998, it made sense to have copies of NaN/+Inf/-Inf living on the runtime, because Values didn't store doubles inline. That hasn't been true for a long time. This patch gets rid of those. Differential Revision: https://phabricator.services.mozilla.com/D29868
dom/canvas/CanvasRenderingContext2D.cpp
js/public/Value.h
js/src/builtin/MapObject.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/CompileWrappers.cpp
js/src/jit/CompileWrappers.h
js/src/jit/IonBuilder.cpp
js/src/jit/MCallOptimize.cpp
js/src/jit/TypePolicy.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsnum.cpp
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1922,17 +1922,17 @@ void CanvasRenderingContext2D::GetMozCur
   if (!mTarget) {
     MatrixToJSObject(aCx, Matrix(), aResult, aError);
     return;
   }
 
   Matrix ctm = mTarget->GetTransform();
 
   if (!ctm.Invert()) {
-    double NaN = JS_GetNaNValue(aCx).toDouble();
+    double NaN = JS::GenericNaN();
     ctm = Matrix(NaN, NaN, NaN, NaN, NaN, NaN);
   }
 
   MatrixToJSObject(aCx, ctm, aResult, aError);
 }
 
 //
 // colors
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -529,18 +529,16 @@ union alignas(8) Value {
     MOZ_ASSERT(toInt32() == i);
   }
 
   void setDouble(double d) {
     *this = Value(d);
     MOZ_ASSERT(isDouble());
   }
 
-  void setNaN() { setDouble(GenericNaN()); }
-
   void setString(JSString* str) {
     MOZ_ASSERT(js::gc::IsCellPointerValid(str));
     asBits_ = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
     MOZ_ASSERT(toString() == str);
   }
 
   void setSymbol(JS::Symbol* sym) {
     MOZ_ASSERT(js::gc::IsCellPointerValid(sym));
@@ -1044,20 +1042,30 @@ static inline bool IsCanonicalized(doubl
   }
 
   uint64_t bits;
   mozilla::BitwiseCast<uint64_t>(d, &bits);
   return (bits & ~mozilla::FloatingPoint<double>::kSignBit) ==
          detail::CanonicalizedNaNBits;
 }
 
-static inline Value DoubleNaNValue() {
-  Value v;
-  v.setNaN();
-  return v;
+static inline constexpr Value NaNValue() {
+  uint64_t rawBits = detail::CanonicalizedNaNBits;
+#if defined(JS_PUNBOX64)
+  rawBits += JSVAL_PUN64_DOUBLE_ADJUST;
+#endif
+  return Value::fromRawBits(rawBits);
+}
+
+static inline Value InfinityValue() {
+  uint64_t rawBits = detail::InfinityBits;
+#if defined(JS_PUNBOX64)
+  rawBits += JSVAL_PUN64_DOUBLE_ADJUST;
+#endif
+  return Value::fromRawBits(rawBits);
 }
 
 static inline Value Float32Value(float f) {
   Value v;
   v.setDouble(f);
   return v;
 }
 
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -24,18 +24,16 @@
 #include "vm/Interpreter-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
 using mozilla::IsNaN;
 using mozilla::NumberEqualsInt32;
 
-using JS::DoubleNaNValue;
-
 /*** HashableValue **********************************************************/
 
 bool HashableValue::setValue(JSContext* cx, HandleValue v) {
   if (v.isString()) {
     // Atomize so that hash() and operator==() are fast and infallible.
     JSString* str = AtomizeString(cx, v.toString(), DoNotPinAtom);
     if (!str) {
       return false;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -3209,21 +3209,21 @@ bool BaselineCompilerCodeGen::tryOptimiz
   PropertyName* name = handler.script()->getName(handler.pc());
 
   // These names are non-configurable on the global and cannot be shadowed.
   if (name == cx->names().undefined) {
     frame.push(UndefinedValue());
     return true;
   }
   if (name == cx->names().NaN) {
-    frame.push(cx->runtime()->NaNValue);
+    frame.push(JS::NaNValue());
     return true;
   }
   if (name == cx->names().Infinity) {
-    frame.push(cx->runtime()->positiveInfinityValue);
+    frame.push(JS::InfinityValue());
     return true;
   }
 
   return false;
 }
 
 template <>
 bool BaselineInterpreterCodeGen::tryOptimizeGetGlobalName() {
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -51,22 +51,16 @@ const JSAtomState& CompileRuntime::names
 const PropertyName* CompileRuntime::emptyString() {
   return runtime()->emptyString;
 }
 
 const StaticStrings& CompileRuntime::staticStrings() {
   return *runtime()->staticStrings;
 }
 
-const Value& CompileRuntime::NaNValue() { return runtime()->NaNValue; }
-
-const Value& CompileRuntime::positiveInfinityValue() {
-  return runtime()->positiveInfinityValue;
-}
-
 const WellKnownSymbols& CompileRuntime::wellKnownSymbols() {
   return *runtime()->wellKnownSymbols;
 }
 
 const void* CompileRuntime::mainContextPtr() {
   return runtime()->mainContextFromAnyThread();
 }
 
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -37,18 +37,16 @@ class CompileRuntime {
 
   bool jitSupportsFloatingPoint();
   bool hadOutOfMemory();
   bool profilingScripts();
 
   const JSAtomState& names();
   const PropertyName* emptyString();
   const StaticStrings& staticStrings();
-  const Value& NaNValue();
-  const Value& positiveInfinityValue();
   const WellKnownSymbols& wellKnownSymbols();
 
   const void* mainContextPtr();
   uint32_t* addressOfTenuredAllocCount();
   const void* addressOfJitStackLimit();
   const void* addressOfInterruptBits();
   const void* addressOfZone();
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -8329,21 +8329,21 @@ AbortReasonOr<Ok> IonBuilder::jsop_getgn
   // cases *exactly* like Baseline, because it's invalid to add an Ion IC or
   // VM call (that might trigger invalidation) if there's no Baseline IC for
   // this op.
   if (name == names().undefined) {
     pushConstant(UndefinedValue());
     return Ok();
   }
   if (name == names().NaN) {
-    pushConstant(realm->runtime()->NaNValue());
+    pushConstant(JS::NaNValue());
     return Ok();
   }
   if (name == names().Infinity) {
-    pushConstant(realm->runtime()->positiveInfinityValue());
+    pushConstant(JS::InfinityValue());
     return Ok();
   }
 
   if (JSObject* obj = testGlobalLexicalBinding(name)) {
     bool emitted = false;
     MOZ_TRY(getStaticName(&emitted, obj, name));
     if (emitted) {
       return Ok();
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -38,17 +38,16 @@
 #include "vm/JSScript-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/StringObject-inl.h"
 
 using mozilla::ArrayLength;
 using mozilla::AssertedCast;
 using mozilla::Maybe;
 
-using JS::DoubleNaNValue;
 using JS::RegExpFlag;
 using JS::RegExpFlags;
 using JS::TrackedOutcome;
 
 namespace js {
 namespace jit {
 
 // Returns true if |native| can be inlined cross-realm. Especially inlined
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -10,18 +10,16 @@
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-using JS::DoubleNaNValue;
-
 static void EnsureOperandNotFloat32(TempAllocator& alloc, MInstruction* def,
                                     unsigned op) {
   MDefinition* in = def->getOperand(op);
   if (in->type() == MIRType::Float32) {
     MToDouble* replace = MToDouble::New(alloc, in);
     def->block()->insertBefore(def, replace);
     if (def->isRecoveredOnBailout()) {
       replace->setRecoveredOnBailout();
@@ -954,17 +952,17 @@ bool StoreUnboxedScalarPolicy::adjustVal
       break;
     case MIRType::Null:
       value->setImplicitlyUsedUnchecked();
       value = MConstant::New(alloc, Int32Value(0));
       ins->block()->insertBefore(ins, value->toInstruction());
       break;
     case MIRType::Undefined:
       value->setImplicitlyUsedUnchecked();
-      value = MConstant::New(alloc, DoubleNaNValue());
+      value = MConstant::New(alloc, JS::NaNValue());
       ins->block()->insertBefore(ins, value->toInstruction());
       break;
     case MIRType::Object:
     case MIRType::String:
     case MIRType::Symbol:
     case MIRType::BigInt:
       value = BoxAt(alloc, ins, value);
       break;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -263,28 +263,16 @@ JS_PUBLIC_API bool JS::ObjectOpResult::f
 }
 
 JS_PUBLIC_API bool JS::ObjectOpResult::failNotDataDescriptor() {
   return fail(JSMSG_NOT_DATA_DESCRIPTOR);
 }
 
 JS_PUBLIC_API int64_t JS_Now() { return PRMJ_Now(); }
 
-JS_PUBLIC_API Value JS_GetNaNValue(JSContext* cx) {
-  return cx->runtime()->NaNValue;
-}
-
-JS_PUBLIC_API Value JS_GetNegativeInfinityValue(JSContext* cx) {
-  return cx->runtime()->negativeInfinityValue;
-}
-
-JS_PUBLIC_API Value JS_GetPositiveInfinityValue(JSContext* cx) {
-  return cx->runtime()->positiveInfinityValue;
-}
-
 JS_PUBLIC_API Value JS_GetEmptyStringValue(JSContext* cx) {
   return StringValue(cx->runtime()->emptyString);
 }
 
 JS_PUBLIC_API JSString* JS_GetEmptyString(JSContext* cx) {
   MOZ_ASSERT(cx->emptyString());
   return cx->emptyString();
 }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -245,22 +245,16 @@ static MOZ_ALWAYS_INLINE JS::Value JS_Nu
 JS_PUBLIC_API bool JS_StringHasBeenPinned(JSContext* cx, JSString* str);
 
 /************************************************************************/
 
 /** Microseconds since the epoch, midnight, January 1, 1970 UTC. */
 extern JS_PUBLIC_API int64_t JS_Now(void);
 
 /** Don't want to export data, so provide accessors for non-inline Values. */
-extern JS_PUBLIC_API JS::Value JS_GetNaNValue(JSContext* cx);
-
-extern JS_PUBLIC_API JS::Value JS_GetNegativeInfinityValue(JSContext* cx);
-
-extern JS_PUBLIC_API JS::Value JS_GetPositiveInfinityValue(JSContext* cx);
-
 extern JS_PUBLIC_API JS::Value JS_GetEmptyStringValue(JSContext* cx);
 
 extern JS_PUBLIC_API JSString* JS_GetEmptyString(JSContext* cx);
 
 extern JS_PUBLIC_API bool JS_ValueToObject(JSContext* cx, JS::HandleValue v,
                                            JS::MutableHandleObject objp);
 
 extern JS_PUBLIC_API JSFunction* JS_ValueToFunction(JSContext* cx,
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1409,18 +1409,18 @@ JSObject* js::InitNumberClass(JSContext*
   if (!parseFloat) {
     return nullptr;
   }
   RootedValue parseFloatValue(cx, ObjectValue(*parseFloat));
   if (!DefineDataProperty(cx, ctor, parseFloatId, parseFloatValue, 0)) {
     return nullptr;
   }
 
-  RootedValue valueNaN(cx, cx->runtime()->NaNValue);
-  RootedValue valueInfinity(cx, cx->runtime()->positiveInfinityValue);
+  RootedValue valueNaN(cx, JS::NaNValue());
+  RootedValue valueInfinity(cx, JS::InfinityValue());
 
   // ES5 15.1.1.1, 15.1.1.2
   if (!NativeDefineDataProperty(
           cx, global, cx->names().NaN, valueNaN,
           JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING) ||
       !NativeDefineDataProperty(
           cx, global, cx->names().Infinity, valueInfinity,
           JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING)) {
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -54,17 +54,16 @@
 #include "wasm/WasmSignalHandlers.h"
 
 #include "gc/GC-inl.h"
 #include "vm/JSContext-inl.h"
 
 using namespace js;
 
 using JS::AutoStableStringChars;
-using JS::DoubleNaNValue;
 using mozilla::Atomic;
 using mozilla::DebugOnly;
 using mozilla::NegativeInfinity;
 using mozilla::PodZero;
 using mozilla::PositiveInfinity;
 
 /* static */ MOZ_THREAD_LOCAL(JSContext*) js::TlsContext;
 /* static */
@@ -127,19 +126,16 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
       defaultLocale(nullptr),
       profilingScripts(false),
       scriptAndCountsVector(nullptr),
       lcovOutput_(),
       jitRuntime_(nullptr),
       selfHostingGlobal_(nullptr),
       gc(thisFromCtor()),
       gcInitialized(false),
-      NaNValue(DoubleNaNValue()),
-      negativeInfinityValue(DoubleValue(NegativeInfinity<double>())),
-      positiveInfinityValue(DoubleValue(PositiveInfinity<double>())),
       emptyString(nullptr),
       defaultFreeOp_(nullptr),
 #if !EXPOSE_INTL_API
       thousandsSeparator(nullptr),
       decimalSeparator(nullptr),
       numGrouping(nullptr),
 #endif
       beingDestroyed_(false),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -649,21 +649,16 @@ struct JSRuntime : public js::MallocProv
   js::WriteOnceData<bool> gcInitialized;
 
   bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
 
   void lockGC() { gc.lockGC(); }
 
   void unlockGC() { gc.unlockGC(); }
 
-  /* Well-known numbers. */
-  const js::Value NaNValue;
-  const js::Value negativeInfinityValue;
-  const js::Value positiveInfinityValue;
-
   js::WriteOnceData<js::PropertyName*> emptyString;
 
  private:
   js::MainThreadData<js::FreeOp*> defaultFreeOp_;
 
  public:
   js::FreeOp* defaultFreeOp() {
     MOZ_ASSERT(defaultFreeOp_);
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -105,17 +105,17 @@ static bool XPC_WN_Shared_toPrimitive(JS
   THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
   JSType hint;
   if (!GetFirstArgumentAsTypeHint(cx, args, &hint)) {
     return false;
   }
 
   if (hint == JSTYPE_NUMBER) {
-    args.rval().set(JS_GetNaNValue(cx));
+    args.rval().set(NaNValue());
     return true;
   }
 
   MOZ_ASSERT(hint == JSTYPE_STRING || hint == JSTYPE_UNDEFINED);
   ccx.SetName(ccx.GetContext()->GetStringID(XPCJSContext::IDX_TO_STRING));
   ccx.SetArgsAndResultPtr(0, nullptr, args.rval().address());
 
   XPCNativeMember* member = ccx.GetMember();