Bug 838558 - Kill object equality hook. r=jorendorff
authorTom Schuster <evilpies@gmail.com>
Mon, 11 Feb 2013 21:06:05 +0100
changeset 121539 d91d6e2bc2587b4c6816574d0872bb3ae0bba746
parent 121538 b9a00a67b74948df2d8b1673e520151028764bad
child 121540 a101d8932e912e50b9752cfca4f166f523695644
push id24296
push useremorley@mozilla.com
push dateTue, 12 Feb 2013 14:43:19 +0000
treeherdermozilla-central@860d7a47b675 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs838558
milestone21.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 838558 - Kill object equality hook. r=jorendorff
js/ipc/ObjectWrapperParent.cpp
js/ipc/ObjectWrapperParent.h
js/src/ion/MIR.cpp
js/src/jsapi-tests/Makefile.in
js/src/jsapi-tests/testCustomIterator.cpp
js/src/jsapi-tests/testExtendedEq.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsclass.h
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobjinlines.h
js/src/jsproxy.cpp
js/src/jstypedarray.cpp
js/src/methodjit/FastOps.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/vm/ArgumentsObject.cpp
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -140,24 +140,17 @@ const js::Class ObjectWrapperParent::sCP
       (JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate,
       (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
       ObjectWrapperParent::CPOW_Convert,
       ObjectWrapperParent::CPOW_Finalize,
       nullptr, // checkAccess
       ObjectWrapperParent::CPOW_Call,
       ObjectWrapperParent::CPOW_HasInstance,
       ObjectWrapperParent::CPOW_Construct,
-      nullptr, // trace
-      {
-          ObjectWrapperParent::CPOW_Equality,
-          nullptr, // outerObject
-          nullptr, // innerObject
-          nullptr, // iteratorObject
-          nullptr, // wrappedObject
-    }
+      nullptr // trace
 };
 
 void
 ObjectWrapperParent::ActorDestroy(ActorDestroyReason)
 {
     if (mObj) {
         JS_SetPrivate(mObj, NULL);
         mObj = NULL;
@@ -693,33 +686,9 @@ ObjectWrapperParent::CPOW_HasInstance(JS
 
     if (!jsval_to_JSVariant(cx, v, &in_v))
         return JS_FALSE;
 
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallHasInstance(in_v,
                                   aco.StatusPtr(), bp) &&
             aco.Ok());
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_Equality(JSContext *cx, JSHandleObject obj, JSHandleValue v,
-                                   JSBool *bp)
-{
-    CPOW_LOG(("Calling CPOW_Equality..."));
-
-    *bp = JS_FALSE;
-    
-    ObjectWrapperParent* self = Unwrap(cx, obj);
-    if (!self)
-        return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Equality");
-
-    if (JSVAL_IS_PRIMITIVE(v))
-        return JS_TRUE;
-
-    ObjectWrapperParent* other = Unwrap(cx, JSVAL_TO_OBJECT(v));
-    if (!other)
-        return JS_TRUE;
-
-    *bp = (self == other);
-    
-    return JS_TRUE;
-}
+}
\ No newline at end of file
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -88,23 +88,20 @@ private:
     static void
     CPOW_Finalize(js::FreeOp* fop, JSObject* obj);
 
     static JSBool
     CPOW_Call(JSContext* cx, unsigned argc, jsval* vp);
 
     static JSBool
     CPOW_Construct(JSContext *cx, unsigned argc, jsval *vp);
-    
+
     static JSBool
     CPOW_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue vp, JSBool *bp);
 
-    static JSBool
-    CPOW_Equality(JSContext *cx, JSHandleObject obj, JSHandleValue v, JSBool *bp);
-
     static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
     static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
                                      jsval* to);
     static bool
     JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from, PObjectWrapperParent** to);
     static bool
     JSObject_from_PObjectWrapperParent(JSContext* cx,
                                        const PObjectWrapperParent* from,
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -1222,26 +1222,24 @@ CanDoValueBitwiseCmp(JSContext *cx, type
         lhs->hasAnyFlag(types::TYPE_FLAG_DOUBLE) ||
         !rhs->knownPrimitiveOrObject() ||
         rhs->hasAnyFlag(types::TYPE_FLAG_STRING) ||
         rhs->hasAnyFlag(types::TYPE_FLAG_DOUBLE))
     {
         return false;
     }
 
-    // Objects with special equality or that emulates undefined are not supported.
+    // Objects that emulate undefined are not supported.
     if (lhs->maybeObject() &&
-        (lhs->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY) ||
-         lhs->hasObjectFlags(cx, types::OBJECT_FLAG_EMULATES_UNDEFINED)))
+        lhs->hasObjectFlags(cx, types::OBJECT_FLAG_EMULATES_UNDEFINED))
     {
         return false;
     }
     if (rhs->maybeObject() &&
-        (rhs->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY) ||
-         rhs->hasObjectFlags(cx, types::OBJECT_FLAG_EMULATES_UNDEFINED)))
+        rhs->hasObjectFlags(cx, types::OBJECT_FLAG_EMULATES_UNDEFINED))
     {
         return false;
     }
 
     // In the loose comparison more values could be the same,
     // but value comparison reporting otherwise.
     if (looseEq) {
 
@@ -1354,22 +1352,16 @@ MCompare::infer(const TypeOracle::Binary
          (rhs == MIRType_Double && SafelyCoercesToDouble(cx, b.lhsTypes))))
     {
         compareType_ = Compare_Double;
         return;
     }
 
     // Handle object comparison.
     if (!relationalEq && lhs == MIRType_Object && rhs == MIRType_Object) {
-        if (b.lhsTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY) ||
-            b.rhsTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY))
-        {
-            return;
-        }
-
         compareType_ = Compare_Object;
         return;
     }
 
     // Handle string comparisons. (Relational string compares are still unsupported).
     if (!relationalEq && lhs == MIRType_String && rhs == MIRType_String) {
         compareType_ = Compare_String;
         return;
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -29,17 +29,16 @@ CPPSRCS = \
   testContexts.cpp \
   testCustomIterator.cpp \
   testDebugger.cpp \
   testDeepFreeze.cpp \
   testDefineGetterSetterNonEnumerable.cpp \
   testDefineProperty.cpp \
   testEnclosingFunction.cpp \
   testErrorCopying.cpp \
-  testExtendedEq.cpp \
   testExternalStrings.cpp \
   testFindSCCs.cpp \
   testFuncCallback.cpp \
   testFunctionProperties.cpp \
   testGCFinalizeCallback.cpp \
   testGCOutOfMemory.cpp \
   testGetPropertyDefault.cpp \
   testHashTable.cpp \
--- a/js/src/jsapi-tests/testCustomIterator.cpp
+++ b/js/src/jsapi-tests/testCustomIterator.cpp
@@ -40,21 +40,20 @@ js::Class HasCustomIterClass = {
     JS_ConvertStub,
     NULL,
     NULL, /* checkAccess */
     NULL, /* call */
     NULL, /* construct */
     NULL, /* hasInstance */
     NULL, /* mark */
     {
-        NULL,
-        NULL,
-        NULL,
+        NULL,       /* outerObject */
+        NULL,       /* innerObject */
         IterHook,
-        NULL
+        false        /* isWrappedNative */
     }
 };
 
 JSBool
 IterClassConstructor(JSContext *cx, unsigned argc, jsval *vp)
 {
     JSObject *obj = JS_NewObjectForConstructor(cx, Jsvalify(&HasCustomIterClass), vp);
     if (!obj)
deleted file mode 100644
--- a/js/src/jsapi-tests/testExtendedEq.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=99:
- *
- * This tests user-specified (via JSExtendedClass) equality operations on
- * trace.
- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include "tests.h"
-#include "jsobj.h"
-
-static JSBool
-my_Equality(JSContext *cx, JS::HandleObject obj, JS::HandleValue, JSBool *bp)
-{
-    *bp = JS_TRUE;
-    return JS_TRUE;
-}
-
-js::Class TestExtendedEq_JSClass = {
-    "TestExtendedEq",
-    0,
-    JS_PropertyStub,       /* addProperty */
-    JS_PropertyStub,       /* delProperty */
-    JS_PropertyStub,       /* getProperty */
-    JS_StrictPropertyStub, /* setProperty */
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    NULL,                  /* convert */
-    NULL,                  /* finalize */
-    NULL,                  /* checkAccess */
-    NULL,                  /* call        */
-    NULL,                  /* construct   */
-    NULL,                  /* hasInstance */
-    NULL,                  /* mark        */
-    {
-        my_Equality,
-        NULL,              /* outerObject    */
-        NULL,              /* innerObject    */
-        NULL,              /* iteratorObject */
-        NULL,              /* wrappedObject  */
-    }
-};
-
-BEGIN_TEST(testExtendedEq_bug530489)
-{
-    JSClass *clasp = (JSClass *) &TestExtendedEq_JSClass;
-
-    CHECK(JS_InitClass(cx, global, global, clasp, NULL, 0, NULL, NULL, NULL, NULL));
-
-    CHECK(JS_DefineObject(cx, global, "obj1", clasp, NULL, 0));
-    CHECK(JS_DefineObject(cx, global, "obj2", clasp, NULL, 0));
-
-    js::RootedValue v(cx);
-    EVAL("(function() { var r; for (var i = 0; i < 10; ++i) r = obj1 == obj2; return r; })()", v.address());
-    CHECK_SAME(v, JSVAL_TRUE);
-    return true;
-}
-END_TEST(testExtendedEq_bug530489)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3324,18 +3324,16 @@ JS_NewObject(JSContext *cx, JSClass *jsc
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
     AutoAssertNoGC nogc;
     if (obj) {
         TypeObjectFlags flags = 0;
-        if (clasp->ext.equality)
-            flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
         if (clasp->emulatesUndefined())
             flags |= OBJECT_FLAG_EMULATES_UNDEFINED;
         if (flags)
             MarkTypeObjectFlags(cx, obj, flags);
     }
 
     JS_ASSERT_IF(obj, obj->getParent());
     return obj;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1086,19 +1086,16 @@ typedef void
 
 /*
  * DEBUG only callback that JSTraceOp implementation can provide to return
  * a string describing the reference traced with JS_CallTracer.
  */
 typedef void
 (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
 
-typedef JSBool
-(* JSEqualityOp)(JSContext *cx, JSHandleObject obj, JSHandleValue v, JSBool *bp);
-
 typedef JSRawObject
 (* JSWeakmapKeyDelegateOp)(JSRawObject obj);
 
 /*
  * Typedef for native functions called by the JS VM.
  *
  * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
  */
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -575,21 +575,19 @@ Class js::ArrayClass = {
     JS_ConvertStub,
     NULL,
     NULL,           /* checkAccess */
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* hasInstance */
     NULL,           /* trace       */
     {
-        NULL,       /* equality    */
         NULL,       /* outerObject */
         NULL,       /* innerObject */
         NULL,       /* iteratorObject  */
-        NULL,       /* unused      */
         false,      /* isWrappedNative */
     }
 };
 
 static bool
 AddLengthProperty(JSContext *cx, HandleObject obj)
 {
     /*
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -221,21 +221,19 @@ typedef void
  */
 struct ClassSizeMeasurement
 {
     JS_CLASS_MEMBERS;
 };
 
 struct ClassExtension
 {
-    JSEqualityOp        equality;
     JSObjectOp          outerObject;
     JSObjectOp          innerObject;
     JSIteratorOp        iteratorObject;
-    void               *unused;
 
     /*
      * isWrappedNative is true only if the class is an XPCWrappedNative.
      * WeakMaps use this to override the wrapper disposal optimization.
      */
     bool                isWrappedNative;
 
     /*
@@ -247,17 +245,17 @@ struct ClassExtension
      * that case, the wrapped object is returned by the wrapper's
      * weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
      * key, it will not be collected (and remain in the weakmap) until the
      * wrapped object is collected.
      */
     JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
 };
 
-#define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,NULL,NULL,false,NULL}
+#define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,false,NULL}
 
 struct ObjectOps
 {
     LookupGenericOp     lookupGeneric;
     LookupPropOp        lookupProperty;
     LookupElementOp     lookupElement;
     LookupSpecialOp     lookupSpecial;
     DefineGenericOp     defineGeneric;
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3850,18 +3850,16 @@ TypeObject::print()
         if (!hasAnyFlags(OBJECT_FLAG_SPARSE_INDEXES))
             printf(" dense");
         if (!hasAnyFlags(OBJECT_FLAG_NON_PACKED))
             printf(" packed");
         if (!hasAnyFlags(OBJECT_FLAG_LENGTH_OVERFLOW))
             printf(" noLengthOverflow");
         if (hasAnyFlags(OBJECT_FLAG_UNINLINEABLE))
             printf(" uninlineable");
-        if (hasAnyFlags(OBJECT_FLAG_SPECIAL_EQUALITY))
-            printf(" specialEquality");
         if (hasAnyFlags(OBJECT_FLAG_EMULATES_UNDEFINED))
             printf(" emulatesUndefined");
         if (hasAnyFlags(OBJECT_FLAG_ITERATED))
             printf(" iterated");
     }
 
     unsigned count = getPropertyCount();
 
@@ -6021,18 +6019,16 @@ JSObject::makeLazyType(JSContext *cx)
         type->interpretedFunction = self->toFunction();
         if (type->interpretedFunction->nonLazyScript()->uninlineable)
             type->flags |= OBJECT_FLAG_UNINLINEABLE;
     }
 
     if (self->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON))
         type->flags |= OBJECT_FLAG_ITERATED;
 
-    if (self->getClass()->ext.equality)
-        type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
     if (self->getClass()->emulatesUndefined())
         type->flags |= OBJECT_FLAG_EMULATES_UNDEFINED;
 
     /*
      * Adjust flags for objects which will have the wrong flags set by just
      * looking at the class prototype key.
      */
 
@@ -6155,19 +6151,16 @@ JSCompartment::getNewType(JSContext *cx,
     /*
      * Set the special equality flag for types whose prototype also has the
      * flag set. This is a hack, :XXX: need a real correspondence between
      * types and the possible js::Class of objects with that type.
      */
     if (proto.isObject()) {
         RootedObject obj(cx, proto.toObject());
 
-        if (obj->hasSpecialEquality())
-            type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
-
         if (fun)
             CheckNewScriptProperties(cx, type, fun);
 
         if (obj->isRegExp()) {
             AddTypeProperty(cx, type, "source", types::Type::StringType());
             AddTypeProperty(cx, type, "global", types::Type::BooleanType());
             AddTypeProperty(cx, type, "ignoreCase", types::Type::BooleanType());
             AddTypeProperty(cx, type, "multiline", types::Type::BooleanType());
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -385,30 +385,27 @@ enum {
      * Whether any objects this represents may be arrays whose length does not
      * fit in an int32.
      */
     OBJECT_FLAG_LENGTH_OVERFLOW       = 0x00040000,
 
     /* Whether any represented script is considered uninlineable in JM. */
     OBJECT_FLAG_UNINLINEABLE          = 0x00080000,
 
-    /* Whether any objects have an equality hook. */
-    OBJECT_FLAG_SPECIAL_EQUALITY      = 0x00100000,
-
     /* Whether any objects have been iterated over. */
-    OBJECT_FLAG_ITERATED              = 0x00200000,
+    OBJECT_FLAG_ITERATED              = 0x00100000,
 
     /* For a global object, whether flags were set on the RegExpStatics. */
-    OBJECT_FLAG_REGEXP_FLAGS_SET      = 0x00400000,
+    OBJECT_FLAG_REGEXP_FLAGS_SET      = 0x00200000,
 
     /* Whether any objects emulate undefined; see EmulatesUndefined. */
-    OBJECT_FLAG_EMULATES_UNDEFINED    = 0x00800000,
+    OBJECT_FLAG_EMULATES_UNDEFINED    = 0x00400000,
 
     /* Flags which indicate dynamic properties of represented objects. */
-    OBJECT_FLAG_DYNAMIC_MASK          = 0x00ff0000,
+    OBJECT_FLAG_DYNAMIC_MASK          = 0x007f0000,
 
     /*
      * Whether all properties of this object are considered unknown.
      * If set, all flags in DYNAMIC_MASK will also be set.
      */
     OBJECT_FLAG_UNKNOWN_PROPERTIES    = 0x80000000,
 
     /* Mask for objects created with unknown properties. */
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -580,27 +580,16 @@ js::LooselyEqual(JSContext *cx, const Va
             double l = lval.toDouble(), r = rval.toDouble();
             *result = (l == r);
             return true;
         }
 
         if (lval.isObject()) {
             JSObject *l = &lval.toObject();
             JSObject *r = &rval.toObject();
-
-            if (JSEqualityOp eq = l->getClass()->ext.equality) {
-                JSBool res;
-                RootedObject lobj(cx, l);
-                RootedValue r(cx, rval);
-                if (!eq(cx, lobj, r, &res))
-                    return false;
-                *result = !!res;
-                return true;
-            }
-
             *result = l == r;
             return true;
         }
 
         *result = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
         return true;
     }
 
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -850,21 +850,19 @@ Class PropertyIteratorObject::class_ = {
     JS_ConvertStub,
     finalize,
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* hasInstance */
     trace,
     {
-        NULL,                /* equality       */
         NULL,                /* outerObject    */
         NULL,                /* innerObject    */
         iterator_iteratorObject,
-        NULL                 /* unused  */
     }
 };
 
 const uint32_t CLOSED_INDEX = UINT32_MAX;
 
 JSObject *
 ElementIteratorObject::create(JSContext *cx, Handle<Value> target)
 {
@@ -1410,21 +1408,19 @@ Class js::GeneratorClass = {
     JS_ConvertStub,
     generator_finalize,
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* hasInstance */
     generator_trace,
     {
-        NULL,                /* equality       */
         NULL,                /* outerObject    */
         NULL,                /* innerObject    */
         iterator_iteratorObject,
-        NULL                 /* unused */
     }
 };
 
 /*
  * Called from the JSOP_GENERATOR case in the interpreter, with fp referring
  * to the frame by which the generator function was activated.  Create a new
  * JSGenerator object, which contains its own StackFrame that we populate
  * from *fp.  We know that upon return, the JSOP_GENERATOR opcode will return
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -784,18 +784,16 @@ JSObject::clearType(JSContext *cx, js::H
     obj->type_ = type;
     return true;
 }
 
 inline void
 JSObject::setType(js::types::TypeObject *newType)
 {
     JS_ASSERT(newType);
-    JS_ASSERT_IF(hasSpecialEquality(),
-                 newType->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY));
     JS_ASSERT_IF(getClass()->emulatesUndefined(),
                  newType->hasAnyFlags(js::types::OBJECT_FLAG_EMULATES_UNDEFINED));
     JS_ASSERT(!hasSingletonType());
     JS_ASSERT(compartment() == newType->compartment());
     type_ = newType;
 }
 
 inline js::TaggedProto
@@ -870,21 +868,16 @@ inline bool JSObject::isIndexed() const
     return lastProperty()->hasObjectFlag(js::BaseShape::INDEXED);
 }
 
 inline bool JSObject::watched() const
 {
     return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
 }
 
-inline bool JSObject::hasSpecialEquality() const
-{
-    return !!getClass()->ext.equality;
-}
-
 inline bool JSObject::isArray() const { return hasClass(&js::ArrayClass); }
 inline bool JSObject::isArguments() const { return isNormalArguments() || isStrictArguments(); }
 inline bool JSObject::isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
 inline bool JSObject::isBlock() const { return hasClass(&js::BlockClass); }
 inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
 inline bool JSObject::isCall() const { return hasClass(&js::CallClass); }
 inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
 inline bool JSObject::isDataView() const { return hasClass(&js::DataViewClass); }
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -2841,21 +2841,19 @@ proxy_HasInstance(JSContext *cx, HandleO
     if (!Proxy::hasInstance(cx, proxy, v, &b))
         return false;
     *bp = !!b;
     return true;
 }
 
 #define PROXY_CLASS_EXT                             \
     {                                               \
-        NULL,                /* equality */         \
         NULL,                /* outerObject */      \
         NULL,                /* innerObject */      \
         NULL,                /* iteratorObject */   \
-        NULL,                /* unused */           \
         false,               /* isWrappedNative */  \
         proxy_WeakmapKeyDelegate                    \
     }
 
 JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
     "Proxy",
     Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4),
     JS_PropertyStub,         /* addProperty */
@@ -2918,21 +2916,19 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
     JS_ConvertStub,
     proxy_Finalize,          /* finalize    */
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* hasInstance */
     NULL,                    /* construct   */
     proxy_TraceObject,       /* trace       */
     {
-        NULL,                /* equality    */
         NULL,                /* outerObject */
         proxy_innerObject,
         NULL,                /* iteratorObject */
-        NULL,                /* unused */
         false,               /* isWrappedNative */
         proxy_WeakmapKeyDelegate
     },
     {
         proxy_LookupGeneric,
         proxy_LookupProperty,
         proxy_LookupElement,
         proxy_LookupSpecial,
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -3313,21 +3313,19 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Flo
     JS_ConvertStub,                                                            \
     NULL,                    /* finalize */                                    \
     NULL,                    /* checkAccess */                                 \
     NULL,                    /* call        */                                 \
     NULL,                    /* construct   */                                 \
     NULL,                    /* hasInstance */                                 \
     _typedArray::obj_trace,  /* trace       */                                 \
     {                                                                          \
-        NULL,       /* equality    */                                          \
         NULL,       /* outerObject */                                          \
         NULL,       /* innerObject */                                          \
         NULL,       /* iteratorObject  */                                      \
-        NULL,       /* unused      */                                          \
         false,      /* isWrappedNative */                                      \
     },                                                                         \
     {                                                                          \
         _typedArray::obj_lookupGeneric,                                        \
         _typedArray::obj_lookupProperty,                                       \
         _typedArray::obj_lookupElement,                                        \
         _typedArray::obj_lookupSpecial,                                        \
         _typedArray::obj_defineGeneric,                                        \
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -377,57 +377,45 @@ CompileStatus
 mjit::Compiler::jsop_equality_obj_obj(JSOp op, jsbytecode *target, JSOp fused)
 {
     FrameEntry *rhs = frame.peek(-1);
     FrameEntry *lhs = frame.peek(-2);
 
     JS_ASSERT(cx->typeInferenceEnabled() &&
               lhs->isType(JSVAL_TYPE_OBJECT) && rhs->isType(JSVAL_TYPE_OBJECT));
 
-    /*
-     * Handle equality between two objects. We have to ensure there is no
-     * special equality operator on either object, if that passes then
-     * this is a pointer comparison.
-     */
-    types::StackTypeSet *lhsTypes = analysis->poppedTypes(PC, 1);
-    types::StackTypeSet *rhsTypes = analysis->poppedTypes(PC, 0);
-    if (!lhsTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY) &&
-        !rhsTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY)) {
-        /* :TODO: Merge with jsop_relational_int? */
-        JS_ASSERT_IF(!target, fused != JSOP_IFEQ);
-        frame.forgetMismatchedObject(lhs);
-        frame.forgetMismatchedObject(rhs);
-        Assembler::Condition cond = GetCompareCondition(op, fused);
-        if (target) {
-            Jump sj = stubcc.masm.branchTest32(GetStubCompareCondition(fused),
-                                               Registers::ReturnReg, Registers::ReturnReg);
-            if (!frame.syncForBranch(target, Uses(2)))
-                return Compile_Error;
-            RegisterID lreg = frame.tempRegForData(lhs);
-            frame.pinReg(lreg);
-            RegisterID rreg = frame.tempRegForData(rhs);
-            frame.unpinReg(lreg);
-            Jump fast = masm.branchPtr(cond, lreg, rreg);
-            frame.popn(2);
-            return jumpAndRun(fast, target, &sj) ? Compile_Okay : Compile_Error;
-        } else {
-            RegisterID result = frame.allocReg();
-            RegisterID lreg = frame.tempRegForData(lhs);
-            frame.pinReg(lreg);
-            RegisterID rreg = frame.tempRegForData(rhs);
-            frame.unpinReg(lreg);
-            masm.branchValue(cond, lreg, rreg, result);
-
-            frame.popn(2);
-            frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, result);
-            return Compile_Okay;
-        }
+    /* :TODO: Merge with jsop_relational_int? */
+    JS_ASSERT_IF(!target, fused != JSOP_IFEQ);
+    frame.forgetMismatchedObject(lhs);
+    frame.forgetMismatchedObject(rhs);
+    Assembler::Condition cond = GetCompareCondition(op, fused);
+    if (target) {
+        Jump sj = stubcc.masm.branchTest32(GetStubCompareCondition(fused),
+                                           Registers::ReturnReg, Registers::ReturnReg);
+        if (!frame.syncForBranch(target, Uses(2)))
+            return Compile_Error;
+        RegisterID lreg = frame.tempRegForData(lhs);
+        frame.pinReg(lreg);
+        RegisterID rreg = frame.tempRegForData(rhs);
+        frame.unpinReg(lreg);
+        Jump fast = masm.branchPtr(cond, lreg, rreg);
+        frame.popn(2);
+        return jumpAndRun(fast, target, &sj) ? Compile_Okay : Compile_Error;
     }
 
-    return Compile_Skipped;
+    RegisterID result = frame.allocReg();
+    RegisterID lreg = frame.tempRegForData(lhs);
+    frame.pinReg(lreg);
+    RegisterID rreg = frame.tempRegForData(rhs);
+    frame.unpinReg(lreg);
+    masm.branchValue(cond, lreg, rreg, result);
+
+    frame.popn(2);
+    frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, result);
+    return Compile_Okay;
 }
 
 bool
 mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused)
 {
     FrameEntry *rhs = frame.peek(-1);
     FrameEntry *lhs = frame.peek(-2);
 
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -292,22 +292,16 @@ class EqualityCompiler : public BaseComp
             linkToStub(lhsFail);
         }
 
         if (!rvr.isConstant() && !rvr.isType(JSVAL_TYPE_OBJECT)) {
             Jump rhsFail = masm.testObject(Assembler::NotEqual, rvr.typeReg());
             linkToStub(rhsFail);
         }
 
-        masm.loadObjClass(lvr.dataReg(), ic.tempReg);
-        Jump lhsHasEq = masm.branchPtr(Assembler::NotEqual,
-                                       Address(ic.tempReg, offsetof(Class, ext.equality)),
-                                       ImmPtr(NULL));
-        linkToStub(lhsHasEq);
-
         if (rvr.isConstant()) {
             JSObject *obj = &rvr.value().toObject();
             Jump test = masm.branchPtr(ic.cond, lvr.dataReg(), ImmPtr(obj));
             linkTrue(test);
         } else {
             Jump test = masm.branchPtr(ic.cond, lvr.dataReg(), rvr.dataReg());
             linkTrue(test);
         }
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -490,26 +490,17 @@ StubEqualityOp(VMFrame &f)
             double l = lval.toDouble();
             double r = rval.toDouble();
             if (EQ)
                 cond = (l == r);
             else
                 cond = (l != r);
         } else if (lval.isObject()) {
             JSObject *l = &lval.toObject(), *r = &rval.toObject();
-            if (JSEqualityOp eq = l->getClass()->ext.equality) {
-                JSBool equal;
-                RootedObject lobj(cx, l);
-                RootedValue r(cx, rval);
-                if (!eq(cx, lobj, r, &equal))
-                    return false;
-                cond = !!equal == EQ;
-            } else {
-                cond = (l == r) == EQ;
-            }
+            cond = (l == r) == EQ;
         } else if (lval.isNullOrUndefined()) {
             cond = EQ;
         } else {
             cond = (lval.payloadAsRawUint32() == rval.payloadAsRawUint32()) == EQ;
         }
     } else {
         if (lval.isNullOrUndefined()) {
             cond = (rval.isNullOrUndefined() ||
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -525,21 +525,19 @@ Class js::NormalArgumentsObjectClass = {
     JS_ConvertStub,
     ArgumentsObject::finalize,
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* hasInstance */
     ArgumentsObject::trace,
     {
-        NULL,       /* equality    */
         NULL,       /* outerObject */
         NULL,       /* innerObject */
         NULL,       /* iteratorObject  */
-        NULL,       /* unused      */
         false,      /* isWrappedNative */
     }
 };
 
 /*
  * Strict mode arguments is significantly less magical than non-strict mode
  * arguments, so it is represented by a different class while sharing some
  * functionality.
@@ -558,16 +556,14 @@ Class js::StrictArgumentsObjectClass = {
     JS_ConvertStub,
     ArgumentsObject::finalize,
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* hasInstance */
     ArgumentsObject::trace,
     {
-        NULL,       /* equality    */
         NULL,       /* outerObject */
         NULL,       /* innerObject */
         NULL,       /* iteratorObject  */
-        NULL,       /* unused      */
         false,      /* isWrappedNative */
     }
 };