Bug 1189750 - Remove unused JM-related PCCounts counters. r=bhackett
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Mon, 03 Aug 2015 11:48:27 +0200
changeset 287512 38a6de3a85b1615b4f222afa824e824c82aaaefe
parent 287511 a1e0d8d8b26d979cde5f3fc6692677b2be212276
child 287513 4b6f2efbdc3621fe91acfd9b7a6fc8f9b867f26b
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1189750
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1189750 - Remove unused JM-related PCCounts counters. r=bhackett
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsscript.cpp
js/src/vm/Interpreter.cpp
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -133,98 +133,17 @@ unsigned
 js::StackDefs(JSScript* script, jsbytecode* pc)
 {
     JSOp op = (JSOp) *pc;
     const JSCodeSpec& cs = js_CodeSpec[op];
     MOZ_ASSERT(cs.ndefs >= 0);
     return cs.ndefs;
 }
 
-static const char * const countBaseNames[] = {
-    "interp"
-};
-
-JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) == PCCounts::BASE_LIMIT);
-
-static const char * const countAccessNames[] = {
-    "infer_mono",
-    "infer_di",
-    "infer_poly",
-    "infer_barrier",
-    "infer_nobarrier",
-    "observe_undefined",
-    "observe_null",
-    "observe_boolean",
-    "observe_int32",
-    "observe_double",
-    "observe_string",
-    "observe_object"
-};
-
-JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
-                 JS_ARRAY_LENGTH(countAccessNames) == PCCounts::ACCESS_LIMIT);
-
-static const char * const countElementNames[] = {
-    "id_int",
-    "id_double",
-    "id_other",
-    "id_unknown",
-    "elem_typed",
-    "elem_packed",
-    "elem_dense",
-    "elem_other"
-};
-
-JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
-                 JS_ARRAY_LENGTH(countAccessNames) +
-                 JS_ARRAY_LENGTH(countElementNames) == PCCounts::ELEM_LIMIT);
-
-static const char * const countPropertyNames[] = {
-    "prop_static",
-    "prop_definite",
-    "prop_other"
-};
-
-JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
-                 JS_ARRAY_LENGTH(countAccessNames) +
-                 JS_ARRAY_LENGTH(countPropertyNames) == PCCounts::PROP_LIMIT);
-
-static const char * const countArithNames[] = {
-    "arith_int",
-    "arith_double",
-    "arith_other",
-    "arith_unknown",
-};
-
-JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
-                 JS_ARRAY_LENGTH(countArithNames) == PCCounts::ARITH_LIMIT);
-
-/* static */ const char*
-PCCounts::countName(JSOp op, size_t which)
-{
-    MOZ_ASSERT(which < numCounts(op));
-
-    if (which < BASE_LIMIT)
-        return countBaseNames[which];
-
-    if (accessOp(op)) {
-        if (which < ACCESS_LIMIT)
-            return countAccessNames[which - BASE_LIMIT];
-        if (elementOp(op))
-            return countElementNames[which - ACCESS_LIMIT];
-        if (propertyOp(op))
-            return countPropertyNames[which - ACCESS_LIMIT];
-        MOZ_CRASH("bad op");
-    }
-
-    if (arithOp(op))
-        return countArithNames[which - BASE_LIMIT];
-
-    MOZ_CRASH("bad op");
-}
+const char * PCCounts::numExecName = "interp";
 
 void
 js::DumpIonScriptCounts(Sprinter* sp, jit::IonScriptCounts* ionCounts)
 {
     Sprint(sp, "IonScript [%lu blocks]:\n", ionCounts->numBlocks());
     for (size_t i = 0; i < ionCounts->numBlocks(); i++) {
         const jit::IonBlockCounts& block = ionCounts->block(i);
         Sprint(sp, "BB #%lu [%05u]", block.id(), block.offset());
@@ -240,36 +159,25 @@ js::DumpIonScriptCounts(Sprinter* sp, ji
 void
 js::DumpPCCounts(JSContext* cx, HandleScript script, Sprinter* sp)
 {
     MOZ_ASSERT(script->hasScriptCounts());
 
 #ifdef DEBUG
     jsbytecode* pc = script->code();
     while (pc < script->codeEnd()) {
-        JSOp op = JSOp(*pc);
         jsbytecode* next = GetNextPc(pc);
 
         if (!Disassemble1(cx, script, pc, script->pcToOffset(pc), true, sp))
             return;
 
-        size_t total = PCCounts::numCounts(op);
-        double* raw = script->getPCCounts(pc).rawCounts();
-
         Sprint(sp, "                  {");
-        bool printed = false;
-        for (size_t i = 0; i < total; i++) {
-            double val = raw[i];
-            if (val) {
-                if (printed)
-                    Sprint(sp, ", ");
-                Sprint(sp, "\"%s\": %.0f", PCCounts::countName(op, i), val);
-                printed = true;
-            }
-        }
+        double val = script->getPCCounts(pc).numExec();
+        if (val)
+            Sprint(sp, "\"%s\": %.0f", PCCounts::numExecName, val);
         Sprint(sp, "}\n");
 
         pc = next;
     }
 #endif
 
     jit::IonScriptCounts* ionCounts = script->getIonCounts();
 
@@ -1841,66 +1749,31 @@ js::GetPCCountScriptSummary(JSContext* c
         if (atom) {
             AppendJSONProperty(buf, "name");
             if (!(str = StringToSource(cx, atom)))
                 return nullptr;
             buf.append(str);
         }
     }
 
-    double baseTotals[PCCounts::BASE_LIMIT] = {0.0};
-    double accessTotals[PCCounts::ACCESS_LIMIT - PCCounts::BASE_LIMIT] = {0.0};
-    double elementTotals[PCCounts::ELEM_LIMIT - PCCounts::ACCESS_LIMIT] = {0.0};
-    double propertyTotals[PCCounts::PROP_LIMIT - PCCounts::ACCESS_LIMIT] = {0.0};
-    double arithTotals[PCCounts::ARITH_LIMIT - PCCounts::BASE_LIMIT] = {0.0};
-
-    for (unsigned i = 0; i < script->length(); i++) {
-        PCCounts& counts = sac.getPCCounts(script->offsetToPC(i));
-        if (!counts)
-            continue;
-
-        JSOp op = (JSOp)script->code()[i];
-        unsigned numCounts = PCCounts::numCounts(op);
+    double total = 0.0;
 
-        for (unsigned j = 0; j < numCounts; j++) {
-            double value = counts.get(j);
-            if (j < PCCounts::BASE_LIMIT) {
-                baseTotals[j] += value;
-            } else if (PCCounts::accessOp(op)) {
-                if (j < PCCounts::ACCESS_LIMIT)
-                    accessTotals[j - PCCounts::BASE_LIMIT] += value;
-                else if (PCCounts::elementOp(op))
-                    elementTotals[j - PCCounts::ACCESS_LIMIT] += value;
-                else if (PCCounts::propertyOp(op))
-                    propertyTotals[j - PCCounts::ACCESS_LIMIT] += value;
-                else
-                    MOZ_CRASH("Bad opcode");
-            } else if (PCCounts::arithOp(op)) {
-                arithTotals[j - PCCounts::BASE_LIMIT] += value;
-            } else {
-                MOZ_CRASH("Bad opcode");
-            }
-        }
+    jsbytecode* codeEnd = script->codeEnd();
+    for (jsbytecode* pc = script->code(); pc < codeEnd; pc = GetNextPc(pc)) {
+        PCCounts& counts = sac.getPCCounts(pc);
+        double value = counts.numExec();
+        total += value;
     }
 
     AppendJSONProperty(buf, "totals");
     buf.append('{');
 
     MaybeComma comma = NO_COMMA;
 
-    AppendArrayJSONProperties(cx, buf, baseTotals, countBaseNames,
-                              JS_ARRAY_LENGTH(baseTotals), comma);
-    AppendArrayJSONProperties(cx, buf, accessTotals, countAccessNames,
-                              JS_ARRAY_LENGTH(accessTotals), comma);
-    AppendArrayJSONProperties(cx, buf, elementTotals, countElementNames,
-                              JS_ARRAY_LENGTH(elementTotals), comma);
-    AppendArrayJSONProperties(cx, buf, propertyTotals, countPropertyNames,
-                              JS_ARRAY_LENGTH(propertyTotals), comma);
-    AppendArrayJSONProperties(cx, buf, arithTotals, countArithNames,
-                              JS_ARRAY_LENGTH(arithTotals), comma);
+    AppendArrayJSONProperties(cx, buf, &total, &PCCounts::numExecName, 1, comma);
 
     uint64_t ionActivity = 0;
     jit::IonScriptCounts* ionCounts = sac.getIonCounts();
     while (ionCounts) {
         for (size_t i = 0; i < ionCounts->numBlocks(); i++)
             ionActivity += ionCounts->block(i).hitCount();
         ionCounts = ionCounts->previous();
     }
@@ -1981,29 +1854,24 @@ GetPCCountJSON(JSContext* cx, const Scri
             JSString* str = JS_NewStringCopyZ(cx, text);
             js_free(text);
             if (!str || !(str = StringToSource(cx, str)))
                 return false;
             buf.append(str);
         }
 
         PCCounts& counts = sac.getPCCounts(pc);
-        unsigned numCounts = PCCounts::numCounts(op);
 
         AppendJSONProperty(buf, "counts");
         buf.append('{');
 
-        MaybeComma comma = NO_COMMA;
-        for (unsigned i = 0; i < numCounts; i++) {
-            double value = counts.get(i);
-            if (value > 0) {
-                AppendJSONProperty(buf, PCCounts::countName(op, i), comma);
-                comma = COMMA;
-                NumberValueToStringBuffer(cx, DoubleValue(value), buf);
-            }
+        double value = counts.numExec();
+        if (value > 0) {
+            AppendJSONProperty(buf, PCCounts::numExecName, NO_COMMA);
+            NumberValueToStringBuffer(cx, DoubleValue(value), buf);
         }
 
         buf.append('}');
         buf.append('}');
     }
 
     buf.append(']');
 
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -767,133 +767,28 @@ GetBytecodeInteger(jsbytecode* pc)
 
 /*
  * Counts accumulated for a single opcode in a script. The counts tracked vary
  * between opcodes, and this structure ensures that counts are accessed in a
  * coherent fashion.
  */
 class PCCounts
 {
-    friend class ::JSScript;
-    double* counts;
-#ifdef DEBUG
-    size_t capacity;
-#elif JS_BITS_PER_WORD == 32
-    void* padding;
-#endif
+    double numExec_;
 
  public:
 
-    enum BaseCounts {
-        BASE_INTERP = 0,
-
-        BASE_LIMIT
-    };
-
-    enum AccessCounts {
-        ACCESS_MONOMORPHIC = BASE_LIMIT,
-        ACCESS_DIMORPHIC,
-        ACCESS_POLYMORPHIC,
-
-        ACCESS_BARRIER,
-        ACCESS_NOBARRIER,
-
-        ACCESS_UNDEFINED,
-        ACCESS_NULL,
-        ACCESS_BOOLEAN,
-        ACCESS_INT32,
-        ACCESS_DOUBLE,
-        ACCESS_STRING,
-        ACCESS_OBJECT,
-
-        ACCESS_LIMIT
-    };
-
-    static bool accessOp(JSOp op) {
-        /*
-         * Access ops include all name, element and property reads, as well as
-         * SETELEM and SETPROP (for ElementCounts/PropertyCounts alignment).
-         */
-        if (op == JSOP_SETELEM || op == JSOP_SETPROP)
-            return true;
-        int format = js_CodeSpec[op].format;
-        return !!(format & (JOF_NAME | JOF_GNAME | JOF_ELEM | JOF_PROP))
-            && !(format & JOF_SET);
+    double& numExec() {
+        return numExec_;
+    }
+    double numExec() const {
+        return numExec_;
     }
 
-    enum ElementCounts {
-        ELEM_ID_INT = ACCESS_LIMIT,
-        ELEM_ID_DOUBLE,
-        ELEM_ID_OTHER,
-        ELEM_ID_UNKNOWN,
-
-        ELEM_OBJECT_TYPED,
-        ELEM_OBJECT_PACKED,
-        ELEM_OBJECT_DENSE,
-        ELEM_OBJECT_OTHER,
-
-        ELEM_LIMIT
-    };
-
-    static bool elementOp(JSOp op) {
-        return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_ELEM);
-    }
-
-    enum PropertyCounts {
-        PROP_STATIC = ACCESS_LIMIT,
-        PROP_DEFINITE,
-        PROP_OTHER,
-
-        PROP_LIMIT
-    };
-
-    static bool propertyOp(JSOp op) {
-        return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_PROP);
-    }
-
-    enum ArithCounts {
-        ARITH_INT = BASE_LIMIT,
-        ARITH_DOUBLE,
-        ARITH_OTHER,
-        ARITH_UNKNOWN,
-
-        ARITH_LIMIT
-    };
-
-    static bool arithOp(JSOp op) {
-        return !!(js_CodeSpec[op].format & JOF_ARITH);
-    }
-
-    static size_t numCounts(JSOp op)
-    {
-        if (accessOp(op)) {
-            if (elementOp(op))
-                return ELEM_LIMIT;
-            if (propertyOp(op))
-                return PROP_LIMIT;
-            return ACCESS_LIMIT;
-        }
-        if (arithOp(op))
-            return ARITH_LIMIT;
-        return BASE_LIMIT;
-    }
-
-    static const char* countName(JSOp op, size_t which);
-
-    double* rawCounts() const { return counts; }
-
-    double& get(size_t which) {
-        MOZ_ASSERT(which < capacity);
-        return counts[which];
-    }
-
-    /* Boolean conversion, for 'if (counters) ...' */
-    operator void*() const {
-        return counts;
-    }
+    static const char* numExecName;
 };
 
 /* Necessary for alignment with the script. */
 JS_STATIC_ASSERT(sizeof(PCCounts) % sizeof(Value) == 0);
 
 static inline jsbytecode*
 GetNextPc(jsbytecode* pc)
 {
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1270,62 +1270,47 @@ JSScript::maybeForwardedScriptSource() c
     return UncheckedUnwrap(MaybeForwarded(sourceObject()))->as<ScriptSourceObject>().source();
 }
 
 bool
 JSScript::initScriptCounts(JSContext* cx)
 {
     MOZ_ASSERT(!hasScriptCounts());
 
-    size_t n = 0;
-
-    for (jsbytecode* pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc))
-        n += PCCounts::numCounts(JSOp(*pc));
-
-    size_t nbytes = (length() * sizeof(PCCounts)) + (n * sizeof(double));
+    // We allocate one PCCounts for each offset, instead of for each bytecode,
+    // because the pcCountsVector maps an offset to a PCCounts structure.
+    size_t nbytes = length() * sizeof(PCCounts);
+
+    // Initialize all PCCounts counters to 0.
     uint8_t* base = zone()->pod_calloc<uint8_t>(nbytes);
     if (!base)
         return false;
 
-    /* Create compartment's scriptCountsMap if necessary. */
+    // Create compartment's scriptCountsMap if necessary.
     ScriptCountsMap* map = compartment()->scriptCountsMap;
     if (!map) {
         map = cx->new_<ScriptCountsMap>();
         if (!map || !map->init()) {
             js_free(base);
             js_delete(map);
             return false;
         }
         compartment()->scriptCountsMap = map;
     }
 
-    uint8_t* cursor = base;
-
     ScriptCounts scriptCounts;
-    scriptCounts.pcCountsVector = (PCCounts*) cursor;
-    cursor += length() * sizeof(PCCounts);
-
-    for (jsbytecode* pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc)) {
-        MOZ_ASSERT(uintptr_t(cursor) % sizeof(double) == 0);
-        scriptCounts.pcCountsVector[pcToOffset(pc)].counts = (double*) cursor;
-        size_t capacity = PCCounts::numCounts(JSOp(*pc));
-#ifdef DEBUG
-        scriptCounts.pcCountsVector[pcToOffset(pc)].capacity = capacity;
-#endif
-        cursor += capacity * sizeof(double);
-    }
-
+    scriptCounts.pcCountsVector = (PCCounts*) base;
+
+    // Register the current ScriptCount in the compartment's map.
     if (!map->putNew(this, scriptCounts)) {
         js_free(base);
         return false;
     }
     hasScriptCounts_ = true; // safe to set this;  we can't fail after this point
 
-    MOZ_ASSERT(size_t(cursor - base) == nbytes);
-
     /* Enable interrupts in any interpreter frames running on this script. */
     for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
         if (iter->isInterpreter())
             iter->asInterpreter()->enableInterruptsIfRunning(this);
     }
 
     return true;
 }
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1983,17 +1983,17 @@ CASE(EnableInterruptsPseudoOpcode)
     if (cx->runtime()->profilingScripts) {
         if (!script->hasScriptCounts())
             script->initScriptCounts(cx);
         moreInterrupts = true;
     }
 
     if (script->hasScriptCounts()) {
         PCCounts counts = script->getPCCounts(REGS.pc);
-        counts.get(PCCounts::BASE_INTERP)++;
+        counts.numExec()++;
         moreInterrupts = true;
     }
 
     if (script->isDebuggee()) {
         if (script->stepModeEnabled()) {
             RootedValue rval(cx);
             JSTrapStatus status = JSTRAP_CONTINUE;
             status = Debugger::onSingleStep(cx, &rval);