Bug 1538692 - Part 3: Change bool template parameter to bool enum class. r=mgaudet
authorAndré Bargull <andre.bargull@gmail.com>
Tue, 26 Mar 2019 16:01:36 +0000
changeset 466202 3697baa3225394badb3c53571f4d5870ed002385
parent 466201 e30a80c7854ff12c5c792a10402eed2d4d30c56e
child 466203 37fe2e02b32b448833f461dd17eae533df66b890
push idunknown
push userunknown
push dateunknown
reviewersmgaudet
bugs1538692
milestone68.0a1
Bug 1538692 - Part 3: Change bool template parameter to bool enum class. r=mgaudet Depends on D24707 Differential Revision: https://phabricator.services.mozilla.com/D24892
js/src/jit/BaselineCacheIRCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/IonCacheIRCompiler.cpp
js/src/jit/IonIC.cpp
js/src/jit/VMFunctionList-inl.h
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -931,24 +931,24 @@ bool BaselineCacheIRCompiler::emitCompar
       masm.Push(right);
     } else {
       masm.Push(right);
       masm.Push(left);
     }
 
     using Fn = bool (*)(JSContext*, HandleString, HandleString, bool*);
     if (op == JSOP_EQ || op == JSOP_STRICTEQ) {
-      callVM<Fn, jit::StringsEqual<true>>(masm);
+      callVM<Fn, jit::StringsEqual<EqualityKind::Equal>>(masm);
     } else if (op == JSOP_NE || op == JSOP_STRICTNE) {
-      callVM<Fn, jit::StringsEqual<false>>(masm);
+      callVM<Fn, jit::StringsEqual<EqualityKind::NotEqual>>(masm);
     } else if (op == JSOP_LT || op == JSOP_GT) {
-      callVM<Fn, jit::StringsCompare<true>>(masm);
+      callVM<Fn, jit::StringsCompare<ComparisonKind::LessThan>>(masm);
     } else {
       MOZ_ASSERT(op == JSOP_LE || op == JSOP_GE);
-      callVM<Fn, jit::StringsCompare<false>>(masm);
+      callVM<Fn, jit::StringsCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
     }
 
     stubFrame.leave(masm);
     masm.mov(ReturnReg, scratch);
   }
   masm.bind(&done);
   masm.tagValue(JSVAL_TYPE_BOOLEAN, scratch, output.valueReg());
   return true;
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5714,32 +5714,33 @@ bool DoCompareFallback(JSContext* cx, Ba
       }
       break;
     case JSOP_GE:
       if (!GreaterThanOrEqual(cx, &lhsCopy, &rhsCopy, &out)) {
         return false;
       }
       break;
     case JSOP_EQ:
-      if (!LooselyEqual<true>(cx, &lhsCopy, &rhsCopy, &out)) {
+      if (!LooselyEqual<EqualityKind::Equal>(cx, &lhsCopy, &rhsCopy, &out)) {
         return false;
       }
       break;
     case JSOP_NE:
-      if (!LooselyEqual<false>(cx, &lhsCopy, &rhsCopy, &out)) {
+      if (!LooselyEqual<EqualityKind::NotEqual>(cx, &lhsCopy, &rhsCopy, &out)) {
         return false;
       }
       break;
     case JSOP_STRICTEQ:
-      if (!StrictlyEqual<true>(cx, &lhsCopy, &rhsCopy, &out)) {
+      if (!StrictlyEqual<EqualityKind::Equal>(cx, &lhsCopy, &rhsCopy, &out)) {
         return false;
       }
       break;
     case JSOP_STRICTNE:
-      if (!StrictlyEqual<false>(cx, &lhsCopy, &rhsCopy, &out)) {
+      if (!StrictlyEqual<EqualityKind::NotEqual>(cx, &lhsCopy, &rhsCopy,
+                                                 &out)) {
         return false;
       }
       break;
     default:
       MOZ_ASSERT_UNREACHABLE("Unhandled baseline compare op");
       return false;
   }
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8038,38 +8038,40 @@ void CodeGenerator::visitBinaryV(LBinary
 void CodeGenerator::emitCompareS(LInstruction* lir, JSOp op, Register left,
                                  Register right, Register output) {
   MOZ_ASSERT(lir->isCompareS() || lir->isCompareStrictS());
 
   OutOfLineCode* ool = nullptr;
 
   using Fn = bool (*)(JSContext*, HandleString, HandleString, bool*);
   if (op == JSOP_EQ || op == JSOP_STRICTEQ) {
-    ool = oolCallVM<Fn, jit::StringsEqual<true>>(lir, ArgList(left, right),
-                                                 StoreRegisterTo(output));
+    ool = oolCallVM<Fn, jit::StringsEqual<EqualityKind::Equal>>(
+        lir, ArgList(left, right), StoreRegisterTo(output));
   } else if (op == JSOP_NE || op == JSOP_STRICTNE) {
-    ool = oolCallVM<Fn, jit::StringsEqual<false>>(lir, ArgList(left, right),
-                                                  StoreRegisterTo(output));
+    ool = oolCallVM<Fn, jit::StringsEqual<EqualityKind::NotEqual>>(
+        lir, ArgList(left, right), StoreRegisterTo(output));
   } else if (op == JSOP_LT) {
-    ool = oolCallVM<Fn, jit::StringsCompare<true>>(lir, ArgList(left, right),
-                                                   StoreRegisterTo(output));
+    ool = oolCallVM<Fn, jit::StringsCompare<ComparisonKind::LessThan>>(
+        lir, ArgList(left, right), StoreRegisterTo(output));
   } else if (op == JSOP_LE) {
     // Push the operands in reverse order for JSOP_LE:
     // - |left <= right| is implemented as |right >= left|.
-    ool = oolCallVM<Fn, jit::StringsCompare<false>>(lir, ArgList(right, left),
-                                                    StoreRegisterTo(output));
+    ool =
+        oolCallVM<Fn, jit::StringsCompare<ComparisonKind::GreaterThanOrEqual>>(
+            lir, ArgList(right, left), StoreRegisterTo(output));
   } else if (op == JSOP_GT) {
     // Push the operands in reverse order for JSOP_GT:
     // - |left > right| is implemented as |right < left|.
-    ool = oolCallVM<Fn, jit::StringsCompare<true>>(lir, ArgList(right, left),
-                                                   StoreRegisterTo(output));
+    ool = oolCallVM<Fn, jit::StringsCompare<ComparisonKind::LessThan>>(
+        lir, ArgList(right, left), StoreRegisterTo(output));
   } else {
     MOZ_ASSERT(op == JSOP_GE);
-    ool = oolCallVM<Fn, jit::StringsCompare<false>>(lir, ArgList(left, right),
-                                                    StoreRegisterTo(output));
+    ool =
+        oolCallVM<Fn, jit::StringsCompare<ComparisonKind::GreaterThanOrEqual>>(
+            lir, ArgList(left, right), StoreRegisterTo(output));
   }
 
   masm.compareStrings(op, left, right, output, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitCompareStrictS(LCompareStrictS* lir) {
@@ -8110,29 +8112,29 @@ void CodeGenerator::visitCompareS(LCompa
 void CodeGenerator::visitCompareVM(LCompareVM* lir) {
   pushArg(ToValue(lir, LBinaryV::RhsInput));
   pushArg(ToValue(lir, LBinaryV::LhsInput));
 
   using Fn =
       bool (*)(JSContext*, MutableHandleValue, MutableHandleValue, bool*);
   switch (lir->mir()->jsop()) {
     case JSOP_EQ:
-      callVM<Fn, jit::LooselyEqual<true>>(lir);
+      callVM<Fn, jit::LooselyEqual<EqualityKind::Equal>>(lir);
       break;
 
     case JSOP_NE:
-      callVM<Fn, jit::LooselyEqual<false>>(lir);
+      callVM<Fn, jit::LooselyEqual<EqualityKind::NotEqual>>(lir);
       break;
 
     case JSOP_STRICTEQ:
-      callVM<Fn, jit::StrictlyEqual<true>>(lir);
+      callVM<Fn, jit::StrictlyEqual<EqualityKind::Equal>>(lir);
       break;
 
     case JSOP_STRICTNE:
-      callVM<Fn, jit::StrictlyEqual<false>>(lir);
+      callVM<Fn, jit::StrictlyEqual<EqualityKind::NotEqual>>(lir);
       break;
 
     case JSOP_LT:
       callVM<Fn, jit::LessThan>(lir);
       break;
 
     case JSOP_LE:
       callVM<Fn, jit::LessThanOrEqual>(lir);
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -1331,24 +1331,24 @@ bool IonCacheIRCompiler::emitCompareStri
     masm.Push(right);
   } else {
     masm.Push(right);
     masm.Push(left);
   }
 
   using Fn = bool (*)(JSContext*, HandleString, HandleString, bool*);
   if (op == JSOP_EQ || op == JSOP_STRICTEQ) {
-    callVM<Fn, jit::StringsEqual<true>>(masm);
+    callVM<Fn, jit::StringsEqual<EqualityKind::Equal>>(masm);
   } else if (op == JSOP_NE || op == JSOP_STRICTNE) {
-    callVM<Fn, jit::StringsEqual<false>>(masm);
+    callVM<Fn, jit::StringsEqual<EqualityKind::NotEqual>>(masm);
   } else if (op == JSOP_LT || op == JSOP_GT) {
-    callVM<Fn, jit::StringsCompare<true>>(masm);
+    callVM<Fn, jit::StringsCompare<ComparisonKind::LessThan>>(masm);
   } else {
     MOZ_ASSERT(op == JSOP_LE || op == JSOP_GE);
-    callVM<Fn, jit::StringsCompare<false>>(masm);
+    callVM<Fn, jit::StringsCompare<ComparisonKind::GreaterThanOrEqual>>(masm);
   }
 
   masm.storeCallBoolResult(output.typedReg().gpr());
   masm.bind(&done);
   return true;
 }
 
 static bool GroupHasPropertyTypes(ObjectGroup* group, jsid* id, Value* v) {
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -629,32 +629,32 @@ bool IonCompareIC::update(JSContext* cx,
       }
       break;
     case JSOP_GE:
       if (!GreaterThanOrEqual(cx, &lhsCopy, &rhsCopy, res)) {
         return false;
       }
       break;
     case JSOP_EQ:
-      if (!LooselyEqual<true>(cx, &lhsCopy, &rhsCopy, res)) {
+      if (!LooselyEqual<EqualityKind::Equal>(cx, &lhsCopy, &rhsCopy, res)) {
         return false;
       }
       break;
     case JSOP_NE:
-      if (!LooselyEqual<false>(cx, &lhsCopy, &rhsCopy, res)) {
+      if (!LooselyEqual<EqualityKind::NotEqual>(cx, &lhsCopy, &rhsCopy, res)) {
         return false;
       }
       break;
     case JSOP_STRICTEQ:
-      if (!StrictlyEqual<true>(cx, &lhsCopy, &rhsCopy, res)) {
+      if (!StrictlyEqual<EqualityKind::Equal>(cx, &lhsCopy, &rhsCopy, res)) {
         return false;
       }
       break;
     case JSOP_STRICTNE:
-      if (!StrictlyEqual<false>(cx, &lhsCopy, &rhsCopy, res)) {
+      if (!StrictlyEqual<EqualityKind::NotEqual>(cx, &lhsCopy, &rhsCopy, res)) {
         return false;
       }
       break;
     default:
       MOZ_ASSERT_UNREACHABLE("Unhandled ion compare op");
       return false;
   }
 
--- a/js/src/jit/VMFunctionList-inl.h
+++ b/js/src/jit/VMFunctionList-inl.h
@@ -153,18 +153,18 @@ namespace jit {
   _(IsPossiblyWrappedTypedArray, js::jit::IsPossiblyWrappedTypedArray)         \
   _(IsPrototypeOf, js::IsPrototypeOf)                                          \
   _(Lambda, js::Lambda)                                                        \
   _(LambdaArrow, js::LambdaArrow)                                              \
   _(LeaveWith, js::jit::LeaveWith)                                             \
   _(LessThan, js::jit::LessThan)                                               \
   _(LessThanOrEqual, js::jit::LessThanOrEqual)                                 \
   _(LexicalEnvironmentObjectCreate, js::LexicalEnvironmentObject::create)      \
-  _(LooselyEqual, js::jit::LooselyEqual<true>)                                 \
-  _(LooselyNotEqual, js::jit::LooselyEqual<false>)                             \
+  _(LooselyEqual, js::jit::LooselyEqual<js::jit::EqualityKind::Equal>)         \
+  _(LooselyNotEqual, js::jit::LooselyEqual<js::jit::EqualityKind::NotEqual>)   \
   _(MakeDefaultConstructor, js::MakeDefaultConstructor)                        \
   _(ModValues, js::ModValues)                                                  \
   _(MulValues, js::MulValues)                                                  \
   _(MutatePrototype, js::jit::MutatePrototype)                                 \
   _(NamedLambdaObjectCreateTemplateObject,                                     \
     js::NamedLambdaObject::createTemplateObject)                               \
   _(NativeGetElement, js::NativeGetElement)                                    \
   _(NewArgumentsObject, js::jit::NewArgumentsObject)                           \
@@ -213,31 +213,32 @@ namespace jit {
   _(SetDenseElement, js::jit::SetDenseElement)                                 \
   _(SetFunctionName, js::SetFunctionName)                                      \
   _(SetIntrinsicOperation, js::SetIntrinsicOperation)                          \
   _(SetObjectElementWithReceiver, js::SetObjectElementWithReceiver)            \
   _(SetProperty, js::jit::SetProperty)                                         \
   _(SetPropertySuper, js::SetPropertySuper)                                    \
   _(SingletonObjectLiteralOperation, js::SingletonObjectLiteralOperation)      \
   _(StartDynamicModuleImport, js::StartDynamicModuleImport)                    \
-  _(StrictlyEqual, js::jit::StrictlyEqual<true>)                               \
-  _(StrictlyNotEqual, js::jit::StrictlyEqual<false>)                           \
+  _(StrictlyEqual, js::jit::StrictlyEqual<js::jit::EqualityKind::Equal>)       \
+  _(StrictlyNotEqual, js::jit::StrictlyEqual<js::jit::EqualityKind::NotEqual>) \
   _(StringFlatReplaceString, js::StringFlatReplaceString)                      \
   _(StringFromCharCode, js::jit::StringFromCharCode)                           \
   _(StringFromCodePoint, js::jit::StringFromCodePoint)                         \
   _(StringReplace, js::jit::StringReplace)                                     \
   _(StringSplitHelper, js::jit::StringSplitHelper)                             \
   _(StringSplitString, js::StringSplitString)                                  \
   _(StringToLowerCase, js::StringToLowerCase)                                  \
   _(StringToNumber, js::StringToNumber)                                        \
   _(StringToUpperCase, js::StringToUpperCase)                                  \
-  _(StringsCompareGreaterThanOrEquals, js::jit::StringsCompare<false>)         \
-  _(StringsCompareLessThan, js::jit::StringsCompare<true>)                     \
-  _(StringsEqual, js::jit::StringsEqual<true>)                                 \
-  _(StringsNotEqual, js::jit::StringsEqual<false>)                             \
+  _(StringsCompareGreaterThanOrEquals,                                         \
+    js::jit::StringsCompare<ComparisonKind::GreaterThanOrEqual>)               \
+  _(StringsCompareLessThan, js::jit::StringsCompare<ComparisonKind::LessThan>) \
+  _(StringsEqual, js::jit::StringsEqual<js::jit::EqualityKind::Equal>)         \
+  _(StringsNotEqual, js::jit::StringsEqual<js::jit::EqualityKind::NotEqual>)   \
   _(SubValues, js::SubValues)                                                  \
   _(SubstringKernel, js::SubstringKernel)                                      \
   _(SuperFunOperation, js::SuperFunOperation)                                  \
   _(ThrowBadDerivedReturn, js::jit::ThrowBadDerivedReturn)                     \
   _(ThrowCheckIsObject, js::ThrowCheckIsObject)                                \
   _(ThrowMsgOperation, js::ThrowMsgOperation)                                  \
   _(ThrowObjectCoercible, js::jit::ThrowObjectCoercible)                       \
   _(ThrowOperation, js::ThrowOperation)                                        \
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -338,49 +338,57 @@ bool MutatePrototype(JSContext* cx, Hand
   if (!value.isObjectOrNull()) {
     return true;
   }
 
   RootedObject newProto(cx, value.toObjectOrNull());
   return SetPrototype(cx, obj, newProto);
 }
 
-template <bool Equal>
+template <EqualityKind Kind>
 bool LooselyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
                   bool* res) {
   if (!js::LooselyEqual(cx, lhs, rhs, res)) {
     return false;
   }
-  if (!Equal) {
+  if (Kind != EqualityKind::Equal) {
     *res = !*res;
   }
   return true;
 }
 
-template bool LooselyEqual<true>(JSContext* cx, MutableHandleValue lhs,
-                                 MutableHandleValue rhs, bool* res);
-template bool LooselyEqual<false>(JSContext* cx, MutableHandleValue lhs,
-                                  MutableHandleValue rhs, bool* res);
+template bool LooselyEqual<EqualityKind::Equal>(JSContext* cx,
+                                                MutableHandleValue lhs,
+                                                MutableHandleValue rhs,
+                                                bool* res);
+template bool LooselyEqual<EqualityKind::NotEqual>(JSContext* cx,
+                                                   MutableHandleValue lhs,
+                                                   MutableHandleValue rhs,
+                                                   bool* res);
 
-template <bool Equal>
+template <EqualityKind Kind>
 bool StrictlyEqual(JSContext* cx, MutableHandleValue lhs,
                    MutableHandleValue rhs, bool* res) {
   if (!js::StrictlyEqual(cx, lhs, rhs, res)) {
     return false;
   }
-  if (!Equal) {
+  if (Kind != EqualityKind::Equal) {
     *res = !*res;
   }
   return true;
 }
 
-template bool StrictlyEqual<true>(JSContext* cx, MutableHandleValue lhs,
-                                  MutableHandleValue rhs, bool* res);
-template bool StrictlyEqual<false>(JSContext* cx, MutableHandleValue lhs,
-                                   MutableHandleValue rhs, bool* res);
+template bool StrictlyEqual<EqualityKind::Equal>(JSContext* cx,
+                                                 MutableHandleValue lhs,
+                                                 MutableHandleValue rhs,
+                                                 bool* res);
+template bool StrictlyEqual<EqualityKind::NotEqual>(JSContext* cx,
+                                                    MutableHandleValue lhs,
+                                                    MutableHandleValue rhs,
+                                                    bool* res);
 
 bool LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
               bool* res) {
   return LessThanOperation(cx, lhs, rhs, res);
 }
 
 bool LessThanOrEqual(JSContext* cx, MutableHandleValue lhs,
                      MutableHandleValue rhs, bool* res) {
@@ -392,52 +400,55 @@ bool GreaterThan(JSContext* cx, MutableH
   return GreaterThanOperation(cx, lhs, rhs, res);
 }
 
 bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs,
                         MutableHandleValue rhs, bool* res) {
   return GreaterThanOrEqualOperation(cx, lhs, rhs, res);
 }
 
-template <bool Equal>
+template <EqualityKind Kind>
 bool StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs,
                   bool* res) {
   if (!js::EqualStrings(cx, lhs, rhs, res)) {
     return false;
   }
-  if (!Equal) {
+  if (Kind != EqualityKind::Equal) {
     *res = !*res;
   }
   return true;
 }
 
-template bool StringsEqual<true>(JSContext* cx, HandleString lhs,
-                                 HandleString rhs, bool* res);
-template bool StringsEqual<false>(JSContext* cx, HandleString lhs,
-                                  HandleString rhs, bool* res);
+template bool StringsEqual<EqualityKind::Equal>(JSContext* cx, HandleString lhs,
+                                                HandleString rhs, bool* res);
+template bool StringsEqual<EqualityKind::NotEqual>(JSContext* cx,
+                                                   HandleString lhs,
+                                                   HandleString rhs, bool* res);
 
-template <bool LessThan>
+template <ComparisonKind Kind>
 bool StringsCompare(JSContext* cx, HandleString lhs, HandleString rhs,
                     bool* res) {
   int32_t result;
   if (!js::CompareStrings(cx, lhs, rhs, &result)) {
     return false;
   }
-  if (LessThan) {
+  if (Kind == ComparisonKind::LessThan) {
     *res = result < 0;
   } else {
     *res = result >= 0;
   }
   return true;
 }
 
-template bool StringsCompare<true>(JSContext* cx, HandleString lhs,
-                                   HandleString rhs, bool* res);
-template bool StringsCompare<false>(JSContext* cx, HandleString lhs,
-                                    HandleString rhs, bool* res);
+template bool StringsCompare<ComparisonKind::LessThan>(JSContext* cx,
+                                                       HandleString lhs,
+                                                       HandleString rhs,
+                                                       bool* res);
+template bool StringsCompare<ComparisonKind::GreaterThanOrEqual>(
+    JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
 
 bool StringSplitHelper(JSContext* cx, HandleString str, HandleString sep,
                        HandleObjectGroup group, uint32_t limit,
                        MutableHandleValue result) {
   JSObject* resultObj = StringSplitString(cx, group, str, sep, limit);
   if (!resultObj) {
     return false;
   }
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -833,37 +833,41 @@ bool CheckOverRecursed(JSContext* cx);
 bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame);
 
 MOZ_MUST_USE bool MutatePrototype(JSContext* cx, HandlePlainObject obj,
                                   HandleValue value);
 MOZ_MUST_USE bool InitProp(JSContext* cx, HandleObject obj,
                            HandlePropertyName name, HandleValue value,
                            jsbytecode* pc);
 
-template <bool Equal>
+enum class EqualityKind : bool { NotEqual, Equal };
+
+template <EqualityKind Kind>
 bool LooselyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
                   bool* res);
 
-template <bool Equal>
+template <EqualityKind Kind>
 bool StrictlyEqual(JSContext* cx, MutableHandleValue lhs,
                    MutableHandleValue rhs, bool* res);
 
 bool LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
               bool* res);
 bool LessThanOrEqual(JSContext* cx, MutableHandleValue lhs,
                      MutableHandleValue rhs, bool* res);
 bool GreaterThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
                  bool* res);
 bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs,
                         MutableHandleValue rhs, bool* res);
 
-template <bool Equal>
+template <EqualityKind Kind>
 bool StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
 
-template <bool LessThan>
+enum class ComparisonKind : bool { GreaterThanOrEqual, LessThan };
+
+template <ComparisonKind Kind>
 bool StringsCompare(JSContext* cx, HandleString lhs, HandleString rhs,
                     bool* res);
 
 MOZ_MUST_USE bool StringSplitHelper(JSContext* cx, HandleString str,
                                     HandleString sep, HandleObjectGroup group,
                                     uint32_t limit, MutableHandleValue result);
 
 MOZ_MUST_USE bool ArrayPopDense(JSContext* cx, HandleObject obj,