Bug 522817: move on-trace method write barrier after shape guard, r=brendan
authorDavid Mandelin <dmandelin@mozilla.com>
Tue, 20 Oct 2009 10:55:15 -0700
changeset 34040 0facea043ada23f8cdb2f7abcbd1d4c43302c67e
parent 34039 ebe24de601e56ccfe2ff416063e8e1e96c3fdd93
child 34041 9992a4a638e2598850d67f02672c038cb624513a
child 34296 78c434300011d262285510465d2b5cda4898d758
push idunknown
push userunknown
push dateunknown
reviewersbrendan
bugs522817
milestone1.9.3a1pre
Bug 522817: move on-trace method write barrier after shape guard, r=brendan
js/src/jstracer.cpp
js/src/trace-test/tests/basic/bug522817.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -11136,33 +11136,16 @@ TraceRecorder::setProp(jsval &l, JSPropC
 
     JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->has(sprop));
 
     // Fast path for CallClass. This is about 20% faster than the general case.
     v_ins = get(&v);
     if (OBJ_GET_CLASS(cx, obj) == &js_CallClass)
         return setCallProp(obj, obj_ins, sprop, v_ins, v);
 
-    /*
-     * Setting a function-valued property might need to rebrand the object, so
-     * we emit a call to the method write barrier. There's no need to guard on
-     * this, because functions have distinct trace-type from other values and
-     * branded-ness is implied by the shape, which we've already guarded on.
-     */
-    if (scope->branded() && VALUE_IS_FUNCTION(cx, v) && entry->directHit()) {
-        if (obj == globalObj)
-            RETURN_STOP("can't trace function-valued property set in branded global scope");
-
-        enterDeepBailCall();
-        LIns* args[] = { v_ins, INS_CONSTSPROP(sprop), obj_ins, cx_ins };
-        LIns* ok_ins = lir->insCall(&MethodWriteBarrier_ci, args);
-        guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
-        leaveDeepBailCall();
-    }
-
     // Find obj2. If entry->adding(), the TAG bits are all 0.
     JSObject* obj2 = obj;
     for (jsuword i = PCVCAP_TAG(entry->vcap) >> PCVCAP_PROTOBITS; i; i--)
         obj2 = OBJ_GET_PARENT(cx, obj2);
     for (jsuword j = PCVCAP_TAG(entry->vcap) & PCVCAP_PROTOMASK; j; j--)
         obj2 = OBJ_GET_PROTO(cx, obj2);
     scope = OBJ_SCOPE(obj2);
     JS_ASSERT_IF(entry->adding(), obj2 == obj);
@@ -11171,16 +11154,33 @@ TraceRecorder::setProp(jsval &l, JSPropC
     LIns* map_ins = map(obj_ins);
     CHECK_STATUS(guardNativePropertyOp(obj, map_ins));
     jsuword pcval;
     CHECK_STATUS(guardPropertyCacheHit(obj_ins, map_ins, obj, obj2, entry, pcval));
     JS_ASSERT(scope->object == obj2);
     JS_ASSERT(scope->has(sprop));
     JS_ASSERT_IF(obj2 != obj, sprop->attrs & JSPROP_SHARED);
 
+    /*
+     * Setting a function-valued property might need to rebrand the object, so
+     * we emit a call to the method write barrier. There's no need to guard on
+     * this, because functions have distinct trace-type from other values and
+     * branded-ness is implied by the shape, which we've already guarded on.
+     */
+    if (scope->branded() && VALUE_IS_FUNCTION(cx, v) && entry->directHit()) {
+        if (obj == globalObj)
+            RETURN_STOP("can't trace function-valued property set in branded global scope");
+
+        enterDeepBailCall();
+        LIns* args[] = { v_ins, INS_CONSTSPROP(sprop), obj_ins, cx_ins };
+        LIns* ok_ins = lir->insCall(&MethodWriteBarrier_ci, args);
+        guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
+        leaveDeepBailCall();
+    }
+
     // Add a property to the object if necessary.
     if (entry->adding()) {
         JS_ASSERT(!(sprop->attrs & JSPROP_SHARED));
         if (obj == globalObj)
             RETURN_STOP("adding a property to the global object");
 
         LIns* args[] = { INS_CONSTSPROP(sprop), obj_ins, cx_ins };
         LIns* ok_ins = lir->insCall(&js_AddProperty_ci, args);
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/bug522817.js
@@ -0,0 +1,17 @@
+// This test should not assert in a debug build.
+
+var q1={};
+var $native = function () {
+    for (var i = 0, l = arguments.length; i < l; i++) {
+        arguments[i].extend = function (props) {};
+    }
+};
+$native(q1, Array, String, Number);
+Array.extend({});
+Number.extend({});
+Object.Native = function () {
+    for (var i = 0; i < arguments.length; i++) {
+      arguments[i].eeeeee = (function(){});
+    }
+};
+new Object.Native(q1, Array, String, Number);