Bug 792166 - Fix incorrect handling of |delete| in common accessor checking. (r=djvj)
authorEric Faust <efaustbmo@gmail.com>
Wed, 26 Sep 2012 19:02:56 -0400
changeset 108321 298ef4e7484938f1dd628c6c231c9ec178f0facb
parent 108320 d0d8848ffd07499b5d250d9cd4bac5f9fbf13303
child 108322 19da37cf65ae77ac5254276d83030dfdd091ebee
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersdjvj
bugs792166
milestone18.0a1
Bug 792166 - Fix incorrect handling of |delete| in common accessor checking. (r=djvj)
js/src/ion/IonBuilder.cpp
js/src/jit-test/tests/ion/bug792166-1.js
js/src/jit-test/tests/ion/bug792166-2.js
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -5447,31 +5447,42 @@ IonBuilder::TestCommonPropFunc(JSContext
         // We only support cases with a single prototype shared. This is
         // overwhelmingly more likely than having multiple different prototype
         // chains with the same custom property function.
         if (!foundProto)
             foundProto = proto;
         else if (foundProto != proto)
             return true;
 
-        // Check here to make sure that everyone has Type Objects which known
+        // Check here to make sure that everyone has Type Objects with known
         // properties between them and the proto we found the accessor on. We
         // need those to add freezes safely. NOTE: We do not do this above, as
         // we may be able to freeze all the types up to where we found the
         // property, even if there are unknown types higher in the prototype
         // chain.
         while (curObj != foundProto) {
-            if (curObj->getType(cx)->unknownProperties())
+            types::TypeObject *typeObj = curObj->getType(cx);
+
+            if (typeObj->unknownProperties())
                 return true;
 
-            // If anyone on the chain is watched, TI thinks they have an own
-            // property, which means if they were to actually overwrite the
-            // property accessors, we would never know, since we are freezing on
-            // setting that flag.
-            if (curObj->watched())
+            // Check here to make sure that nobody on the prototype chain is
+            // marked as having the property as an "own property". This can
+            // happen in cases of |delete| having been used, or cases with
+            // watched objects. If TI ever decides to be more accurate about
+            // |delete| handling, this should go back to curObj->watched().
+
+            // Even though we are not directly accessing the properties on the whole
+            // prototype chain, we need to fault in the sets anyway, as we need
+            // to freeze on them.
+            jsid typeId = types::MakeTypeId(cx, id);
+            types::HeapTypeSet *propSet = typeObj->getProperty(cx, typeId, false);
+            if (!propSet)
+                return false;
+            if (propSet->isOwnProperty(cx, typeObj, false))
                 return true;
 
             curObj = curObj->getProto();
         }
     }
 
     // No need to add a freeze if we didn't find anything
     if (!found)
@@ -5513,16 +5524,18 @@ IonBuilder::TestCommonPropFunc(JSContext
         // If we found a Singleton object's own-property, there's nothing to
         // freeze.
         if (obj != foundProto) {
             // Walk the prototype chain. Everyone has to have the property, since we
             // just checked, so propSet cannot be NULL.
             jsid typeId = types::MakeTypeId(cx, id);
             while (true) {
                 types::HeapTypeSet *propSet = curType->getProperty(cx, typeId, false);
+                // This assert is now assured, since we have faulted them in
+                // above.
                 JS_ASSERT(propSet);
                 // Asking, freeze by asking.
                 DebugOnly<bool> isOwn = propSet->isOwnProperty(cx, curType, false);
                 JS_ASSERT(!isOwn);
                 // Don't mark the proto. It will be held down by the shape
                 // guard. This allows us tp use properties found on prototypes
                 // with properties unknown to TI.
                 if (curType->proto == foundProto)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug792166-1.js
@@ -0,0 +1,8 @@
+Object.defineProperty(Object.prototype, 'x', {
+    set: function() {}
+});
+var obj = {};
+for (var i = 0; i < 100 ; ++i) {
+    obj.x = 1;
+    delete obj.x;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug792166-2.js
@@ -0,0 +1,8 @@
+try {
+  __defineGetter__("eval", function() {
+    this["__proto__"]
+  })
+  delete this["__proto__"]
+  this["__proto__"]
+} catch (e) {}
+eval