Revision: 13255
Author:   [email protected]
Date:     Thu Dec 20 07:03:30 2012
Log: Object.observe: fix observation for optimised in/decrement and compound assignment.

[email protected]
BUG=v8:2409

Review URL: https://codereview.chromium.org/11642042
http://code.google.com/p/v8/source/detail?r=13255

Modified:
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js

=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Dec 18 08:25:45 2012
+++ /branches/bleeding_edge/src/hydrogen.cc     Thu Dec 20 07:03:30 2012
@@ -5910,7 +5910,7 @@
       }

       HInstruction* store;
-      if (!monomorphic) {
+      if (!monomorphic || map->is_observed()) {
         // If we don't know the monomorphic type, do a generic store.
         CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr));
       } else {
@@ -8265,7 +8265,7 @@
       input = Pop();

       HInstruction* store;
-      if (!monomorphic) {
+      if (!monomorphic || map->is_observed()) {
         // If we don't know the monomorphic type, do a generic store.
         CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after));
       } else {
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js Thu Dec 20 06:12:41 2012 +++ /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js Thu Dec 20 07:03:30 2012
@@ -303,7 +303,6 @@


 // Recursive observation.
-/* TODO(rossberg): temporarily disabled until fixed.
 var obj = {a: 1};
 var callbackCount = 0;
 function recursiveObserver(r) {
@@ -331,7 +330,6 @@
 ++obj1.a;
 Object.deliverChangeRecords(recursiveObserver2);
 assertEquals(199, recordCount);
-*/


 // Observing named properties.
@@ -360,6 +358,9 @@
 Object.defineProperty(obj, "a", {get: function() {}, configurable: true});
 Object.defineProperty(obj, "a", {value: 9, writable: true});
 obj.a = 10;
+++obj.a;
+obj.a++;
+obj.a *= 3;
 delete obj.a;
 Object.defineProperty(obj, "a", {value: 11, configurable: true});
 Object.deliverChangeRecords(observer.callback);
@@ -381,7 +382,10 @@
   { object: obj, name: "a", type: "new" },
   { object: obj, name: "a", type: "reconfigured" },
   { object: obj, name: "a", type: "updated", oldValue: 9 },
-  { object: obj, name: "a", type: "deleted", oldValue: 10 },
+  { object: obj, name: "a", type: "updated", oldValue: 10 },
+  { object: obj, name: "a", type: "updated", oldValue: 11 },
+  { object: obj, name: "a", type: "updated", oldValue: 12 },
+  { object: obj, name: "a", type: "deleted", oldValue: 36 },
   { object: obj, name: "a", type: "new" },
 ]);

@@ -412,6 +416,9 @@
 Object.defineProperty(obj, "1", {get: function() {}, configurable: true});
 Object.defineProperty(obj, "1", {value: 9, writable: true});
 obj[1] = 10;
+++obj[1];
+obj[1]++;
+obj[1] *= 3;
 delete obj[1];
 Object.defineProperty(obj, "1", {value: 11, configurable: true});
 Object.deliverChangeRecords(observer.callback);
@@ -433,7 +440,10 @@
   { object: obj, name: "1", type: "new" },
   { object: obj, name: "1", type: "reconfigured" },
   { object: obj, name: "1", type: "updated", oldValue: 9 },
-  { object: obj, name: "1", type: "deleted", oldValue: 10 },
+  { object: obj, name: "1", type: "updated", oldValue: 10 },
+  { object: obj, name: "1", type: "updated", oldValue: 11 },
+  { object: obj, name: "1", type: "updated", oldValue: 12 },
+  { object: obj, name: "1", type: "deleted", oldValue: 36 },
   { object: obj, name: "1", type: "new" },
 ]);

@@ -470,6 +480,9 @@
Object.defineProperty(obj, prop, {get: function() {}, configurable: true});
   Object.defineProperty(obj, prop, {value: 9, writable: true});
   obj[prop] = 10;
+  ++obj[prop];
+  obj[prop]++;
+  obj[prop] *= 3;
   delete obj[prop];
   Object.defineProperty(obj, prop, {value: 11, configurable: true});
   Object.deliverChangeRecords(observer.callback);
@@ -495,7 +508,10 @@
     { object: obj, name: prop, type: "new" },
     { object: obj, name: prop, type: "reconfigured" },
     { object: obj, name: prop, type: "updated", oldValue: 9 },
-    { object: obj, name: prop, type: "deleted", oldValue: 10 },
+    { object: obj, name: prop, type: "updated", oldValue: 10 },
+    { object: obj, name: prop, type: "updated", oldValue: 11 },
+    { object: obj, name: prop, type: "updated", oldValue: 12 },
+    { object: obj, name: prop, type: "deleted", oldValue: 36 },
     { object: obj, name: prop, type: "new" },
   ]);
   Object.unobserve(obj, observer.callback);
@@ -628,6 +644,9 @@
 arr2.length = 1; // no change expected
 Object.defineProperty(arr2, 'length', {value: 1, writable: false});
 arr3.length = 0;
+++arr3.length;
+arr3.length++;
+arr3.length /= 2;
 Object.defineProperty(arr3, 'length', {value: 5});
 Object.defineProperty(arr3, 'length', {value: 10, writable: false});
 Object.deliverChangeRecords(observer.callback);
@@ -646,6 +665,9 @@
   { object: arr3, name: '0', type: 'deleted', oldValue: 'hello' },
   { object: arr3, name: 'length', type: 'updated', oldValue: 6 },
   { object: arr3, name: 'length', type: 'updated', oldValue: 0 },
+  { object: arr3, name: 'length', type: 'updated', oldValue: 1 },
+  { object: arr3, name: 'length', type: 'updated', oldValue: 2 },
+  { object: arr3, name: 'length', type: 'updated', oldValue: 1 },
   { object: arr3, name: 'length', type: 'reconfigured', oldValue: 5 },
 ]);

@@ -925,39 +947,65 @@

// Check that changes in observation status are detected in all IC states and
 // in optimized code, especially in cases usually using fast elements.
-function TestFastElements(prepopulate, polymorphic, optimize) {
+var mutation = [
+  "a[i] = v",
+  "a[i] ? ++a[i] : a[i] = v",
+  "a[i] ? a[i]++ : a[i] = v",
+  "a[i] ? a[i] += 1 : a[i] = v",
+  "a[i] ? a[i] -= -1 : a[i] = v",
+];
+
+var props = [1, "1", "a"];
+
+function TestFastElements(prop, mutation, prepopulate, polymorphic, optimize) {
   var setElement = eval(
-    "(function setElement(a, i, v) { a[i] = v " +
-    "/* " + prepopulate + " " + polymorphic + " " + optimize + " */" +
+    "(function setElement(a, i, v) { " + mutation + "; " +
+    "/* " + [].join.call(arguments, " ") + " */" +
     "})"
   );
   print("TestFastElements:", setElement);

   var arr = prepopulate ? [1, 2, 3, 4, 5] : [0];
-  setElement(arr, 1, 210);
-  setElement(arr, 1, 211);
+  if (prepopulate) arr[prop] = 2;  // for non-element case
+  setElement(arr, prop, 3);
+  setElement(arr, prop, 4);
   if (polymorphic) setElement(["M", "i", "l", "n", "e", "r"], 0, "m");
   if (optimize) %OptimizeFunctionOnNextCall(setElement);
-  setElement(arr, 1, 212);
+  setElement(arr, prop, 5);

   reset();
   Object.observe(arr, observer.callback);
-  setElement(arr, 1, 989898);
+  setElement(arr, prop, 989898);
   Object.deliverChangeRecords(observer.callback);
   observer.assertCallbackRecords([
-    { object: arr, name: '1', type: 'updated', oldValue: 212 }
+    { object: arr, name: "" + prop, type: 'updated', oldValue: 5 }
   ]);
 }

 for (var b1 = 0; b1 < 2; ++b1)
   for (var b2 = 0; b2 < 2; ++b2)
     for (var b3 = 0; b3 < 2; ++b3)
-      TestFastElements(b1 != 0, b2 != 0, b3 != 0);
+      for (var i in props)
+        for (var j in mutation)
+ TestFastElements(props[i], mutation[j], b1 != 0, b2 != 0, b3 != 0);

-function TestFastElementsLength(polymorphic, optimize, oldSize, newSize) {
+
+var mutation = [
+  "a.length = v",
+  "a.length += newSize - oldSize",
+  "a.length -= oldSize - newSize",
+];
+
+var mutationByIncr = [
+  "++a.length",
+  "a.length++",
+];
+
+function TestFastElementsLength(
+  mutation, polymorphic, optimize, oldSize, newSize) {
   var setLength = eval(
-    "(function setLength(a, n) { a.length = n " +
- "/* " + polymorphic + " " + optimize + " " + oldSize + " " + newSize + " */"
+    "(function setLength(a, v) { " + mutation + "; " +
+    "/* " + [].join.call(arguments, " ") + " */"
     + "})"
   );
   print("TestFastElementsLength:", setLength);
@@ -996,4 +1044,11 @@
   for (var b2 = 0; b2 < 2; ++b2)
     for (var n1 = 0; n1 < 3; ++n1)
       for (var n2 = 0; n2 < 3; ++n2)
-        TestFastElementsLength(b1 != 0, b2 != 0, 20*n1, 20*n2);
+        for (var i in mutation)
+ TestFastElementsLength(mutation[i], b1 != 0, b2 != 0, 20*n1, 20*n2);
+
+for (var b1 = 0; b1 < 2; ++b1)
+  for (var b2 = 0; b2 < 2; ++b2)
+    for (var n = 0; n < 3; ++n)
+      for (var i in mutationByIncr)
+ TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to