Prebrand standard classes with standard methods (610698, r=jorendorff).
authorBrendan Eich <brendan@mozilla.org>
Tue, 09 Nov 2010 11:40:56 -0800
changeset 57748 eab06474c89d13248203dba824dc1fb4babb31a8
parent 57747 a872a7883972e2dc9d6055d7b9ecb7d3dd7ee1f3
child 57749 049145d64214b6a8c16598357e46cfb3077322eb
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersjorendorff
bugs610698
milestone2.0b8pre
Prebrand standard classes with standard methods (610698, r=jorendorff).
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jspropertycache.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3661,16 +3661,25 @@ js_InitClass(JSContext *cx, JSObject *ob
     if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
         (fs && !JS_DefineFunctions(cx, proto, fs)) ||
         (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
         (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
         goto bad;
     }
 
     /*
+     * Pre-brand the prototype and constructor if they have built-in methods.
+     * This avoids extra shape guard branch exits in the tracejitted code.
+     */
+    if (fs && !proto->brand(cx))
+        goto bad;
+    if (ctor != proto && static_fs && !ctor->brand(cx))
+        goto bad;
+
+    /*
      * Make sure proto's emptyShape is available to be shared by objects of
      * this class.  JSObject::emptyShape is a one-slot cache. If we omit this,
      * some other class could snap it up. (The risk is particularly great for
      * Object.prototype.)
      *
      * All callers of JSObject::initSharingEmptyShape depend on this.
      *
      * FIXME: bug 592296 -- js_InitArrayClass should pass &js_SlowArrayClass
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -417,17 +417,17 @@ struct JSObject : js::gc::Cell {
 
     /*
      * A branded object contains plain old methods (function-valued properties
      * without magic getters and setters), and its shape evolves whenever a
      * function value changes.
      */
     bool branded()              { return !!(flags & BRANDED); }
 
-    bool brand(JSContext *cx, uint32 slot, js::Value v);
+    bool brand(JSContext *cx);
     bool unbrand(JSContext *cx);
 
     bool generic()              { return !!(flags & GENERIC); }
     void setGeneric()           { flags |= GENERIC; }
 
     bool hasSpecialEquality()   { return !!(flags & HAS_EQUALITY); }
     
   private:
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -84,17 +84,17 @@ JSObject::preventExtensions(JSContext *c
     if (isNative())
         extensibleShapeChange(cx);
 
     flags |= NOT_EXTENSIBLE;
     return true;
 }
 
 inline bool
-JSObject::brand(JSContext *cx, uint32 slot, js::Value v)
+JSObject::brand(JSContext *cx)
 {
     JS_ASSERT(!generic());
     JS_ASSERT(!branded());
     JS_ASSERT(isNative());
     generateOwnShape(cx);
     if (js_IsPropertyCacheDisabled(cx))  // check for rt->shapeGen overflow
         return false;
     flags |= BRANDED;
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -181,17 +181,17 @@ PropertyCache::fill(JSContext *cx, JSObj
 #ifdef DEBUG_notme
                         fprintf(stderr,
                                 "branding %p (%s) for funobj %p (%s), shape %lu\n",
                                 pobj, pobj->getClass()->name,
                                 JSVAL_TO_OBJECT(v),
                                 JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))),
                                 obj->shape());
 #endif
-                        if (!pobj->brand(cx, shape->slot, v))
+                        if (!pobj->brand(cx))
                             return JS_NO_PROP_CACHE_FILL;
                     }
                     vword.setFunObj(*funobj);
                     break;
                 }
             }
         }