Bug 554955: Make JSObject::setMap not pretend to take a const shape. r=jorendorff
authorJim Blandy <jimb@mozilla.com>
Mon, 31 Jan 2011 12:08:13 -0800
changeset 61700 18a1effafe19ab82f760864f1757e63ac2171b31
parent 61699 26d40e1e80bfbe1b381f8a23344fb5f91ec4624b
child 61701 297b1312f534a4c610c4d987a7faa394bb84a898
push idunknown
push userunknown
push dateunknown
reviewersjorendorff
bugs554955
milestone2.0b11pre
Bug 554955: Make JSObject::setMap not pretend to take a const shape. r=jorendorff Without this patch, JSObject::setMap takes a const js::Shape *, which is kind of misleading. The object will not actually treat the shape as const (it does a const_cast). At all but one call site, setMap's argument is not a const shape --- and in fact, many call sites are installing empty shapes whose role in life is to be extended. The only place where a const js::Shape appears is in setSharedNonNativeMap, which is doing something unusual. The const cast should be there. Changing js::Bindings::lastShape to return a non-const shape is then natural, and cleans up the definition of initCall coming in the next patch.
js/src/jsobj.h
js/src/jsscript.h
js/src/jsscriptinlines.h
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -469,24 +469,24 @@ struct JSObject : js::gc::Cell {
     void setOwnShape(uint32 s)  { flags |= OWN_SHAPE; objShape = s; }
     void clearOwnShape()        { flags &= ~OWN_SHAPE; objShape = map->shape; }
 
   public:
     inline bool nativeEmpty() const;
 
     bool hasOwnShape() const    { return !!(flags & OWN_SHAPE); }
 
-    void setMap(const JSObjectMap *amap) {
+    void setMap(JSObjectMap *amap) {
         JS_ASSERT(!hasOwnShape());
-        map = const_cast<JSObjectMap *>(amap);
+        map = amap;
         objShape = map->shape;
     }
 
     void setSharedNonNativeMap() {
-        setMap(&JSObjectMap::sharedNonNative);
+        setMap(const_cast<JSObjectMap *>(&JSObjectMap::sharedNonNative));
     }
 
     void deletingShapeChange(JSContext *cx, const js::Shape &shape);
     const js::Shape *methodShapeChange(JSContext *cx, const js::Shape &shape);
     bool methodShapeChange(JSContext *cx, uint32 slot);
     void protoShapeChange(JSContext *cx);
     void shadowingShapeChange(JSContext *cx, const js::Shape &shape);
     bool globalObjectOwnShapeChange(JSContext *cx);
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -198,17 +198,17 @@ class Bindings {
     uintN countArgsAndVars() const { return nargs + nvars; }
 
     uintN countLocalNames() const { return nargs + nvars + nupvars; }
 
     bool hasUpvars() const { return nupvars > 0; }
     bool hasLocalNames() const { return countLocalNames() > 0; }
 
     /* Returns the shape lineage generated for these bindings. */
-    inline const js::Shape *lastShape() const;
+    inline js::Shape *lastShape() const;
 
     enum {
         /*
          * A script may have no more than this many arguments, variables, or
          * upvars.
          */
         BINDING_COUNT_LIMIT = 0xFFFF
     };
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -80,17 +80,17 @@ Bindings::clone(JSContext *cx, Bindings 
      * Non-dictionary bindings are fine to share, as are dictionary bindings if
      * they're copy-on-modification.
      */
     JS_ASSERT(!bindings->lastBinding->inDictionary() || bindings->lastBinding->frozen());
 
     *this = *bindings;
 }
 
-const Shape *
+Shape *
 Bindings::lastShape() const
 {
     JS_ASSERT(lastBinding);
     JS_ASSERT_IF(lastBinding->inDictionary(), lastBinding->frozen());
     return lastBinding;
 }
 
 } // namespace js