[INFER] Watch for recompilation triggered by ValueToObject, bug 647183.
authorBrian Hackett <bhackett1024@gmail.com>
Sun, 03 Apr 2011 16:11:46 -0700
changeset 74897 c6bed35e308d1a408582d3af463a8d221b2ad2b1
parent 74896 11f4754d82828de1d5a3a7a45e7325aa63ff1104
child 74898 514f2a3478e4c497a91b8020f95629f5feae55ac
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs647183
milestone2.2a1pre
[INFER] Watch for recompilation triggered by ValueToObject, bug 647183.
js/src/jit-test/tests/jaeger/recompile/bug647183.js
js/src/methodjit/PolyIC.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/recompile/bug647183.js
@@ -0,0 +1,23 @@
+var SECTION = "";
+var VERSION = "";
+function test() {}
+function writeTestCaseResult( expect, actual, string ) {
+  if (typeof document != "object" ||
+!document.location.href.match(/jsreftest.html/)) {
+  }
+}
+TIME_0000  = now = new Date;
+TIME_NOW = now.valueOf();
+function DaysInYear( y ) {
+function MakeDate( day, time ) {
+
+}
+}
+function TimeClip( t ) {
+  if ( isNaN ) { Number.NaN; }
+}
+function runDSTOffsetCachingTestsFraction(part, parts) { print; };
+test_times=( TIME_NOW, TIME_0000, ( SECTION, VERSION+".getUTCMinutes()", 
+             TIME_NOW.test_times,VERSION.SECTION ) , TIME_0000, TIME_0000,
+             0, 0 );
+try { j = 0( SECTION, TimeClip(1.1), 0 ); } catch (e) {}
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -1757,23 +1757,30 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic
                     f.regs.sp[-1].setInt32(str->length());
                 }
                 return;
             }
         }
         atom = f.cx->runtime->atomState.lengthAtom;
     }
 
+    bool usePropCache = pic->usePropCache;
+
+    /*
+     * ValueToObject can trigger recompilations if it lazily initializes any
+     * of the primitive classes (Boolean, Number, String). :XXX: if these
+     * classes are made eager then this monitoring is not necessary.
+     */
+    RecompilationMonitor monitor(f.cx);
+
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-1]);
     if (!obj)
         THROW();
 
-    bool usePropCache = pic->usePropCache;
-
-    if (pic->shouldUpdate(f.cx)) {
+    if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) {
         VoidStubPIC stub = pic->usePropCache
                            ? DisabledGetPropIC
                            : DisabledGetPropICNoCache;
         GetPropCompiler cc(f, script, obj, *pic, atom, stub);
         if (!cc.update()) {
             cc.disable("error");
             THROW();
         }
@@ -1819,42 +1826,38 @@ static void JS_FASTCALL
 DisabledSetPropICNoCache(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::SetPropNoCache<strict>(f, pic->atom);
 }
 
 void JS_FASTCALL
 ic::SetProp(VMFrame &f, ic::PICInfo *pic)
 {
-    JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
-    if (!obj)
-        THROW();
-
     JSScript *script = f.fp()->script();
     JS_ASSERT(pic->isSet());
 
     VoidStubPIC stub = pic->usePropCache
                        ? STRICT_VARIANT(DisabledSetPropIC)
                        : STRICT_VARIANT(DisabledSetPropICNoCache);
 
     // Save this in case the compiler triggers a recompilation of this script.
     JSAtom *atom = pic->atom;
     VoidStubAtom nstub = pic->usePropCache
                          ? STRICT_VARIANT(stubs::SetName)
                          : STRICT_VARIANT(stubs::SetPropNoCache);
 
-    //
-    // Important: We update the PIC before looking up the property so that the
-    // PIC is updated only if the property already exists. The PIC doesn't try
-    // to optimize adding new properties; that is for the slow case.
-    //
-    // Also note, we can't use SetName for PROPINC PICs because the property
+    RecompilationMonitor monitor(f.cx);
+
+    JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
+    if (!obj)
+        THROW();
+
+    // Note, we can't use SetName for PROPINC PICs because the property
     // cache can't handle a GET and SET from the same scripted PC.
-    if (pic->shouldUpdate(f.cx)) {
-
+    if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) {
         SetPropCompiler cc(f, script, obj, *pic, atom, stub);
         LookupStatus status = cc.update();
         if (status == Lookup_Error)
             THROW();
     }
     
     Value rval = f.regs.sp[-1];
     nstub(f, atom);
@@ -2528,31 +2531,33 @@ ic::GetElement(VMFrame &f, ic::GetElemen
 
     // Right now, we don't optimize for strings.
     if (!f.regs.sp[-2].isObject()) {
         ic->disable(cx, "non-object");
         stubs::GetElem(f);
         return;
     }
 
+    Value idval = f.regs.sp[-1];
+
+    RecompilationMonitor monitor(cx);
+
     JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]);
     if (!obj)
         THROW();
 
-    Value idval = f.regs.sp[-1];
-
     jsid id;
     if (idval.isInt32() && INT_FITS_IN_JSID(idval.toInt32())) {
         id = INT_TO_JSID(idval.toInt32());
     } else {
         if (!js_InternNonIntElementId(cx, obj, idval, &id))
             THROW();
     }
 
-    if (ic->shouldUpdate(cx)) {
+    if (!monitor.recompiled() && ic->shouldUpdate(cx)) {
 #ifdef DEBUG
         f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC);
 #endif
         LookupStatus status = ic->update(f, cx, obj, idval, id, &f.regs.sp[-2]);
         if (status != Lookup_Uncacheable) {
             if (status == Lookup_Error)
                 THROW();