--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -152,19 +152,52 @@ static bool InferSpewActive(SpewChannel
if (strstr(env, "full")) {
for (unsigned i = 0; i < SPEW_COUNT; i++)
active[i] = true;
}
}
return active[channel];
}
+static bool InferSpewColorable()
+{
+ /* Only spew colors on xterm-color to not screw up emacs. */
+ const char *env = getenv("TERM");
+ if (!env)
+ return false;
+ return strcmp(env, "xterm-color") == 0;
+}
+
#ifdef DEBUG
const char *
+types::InferSpewColor(TypeConstraint *constraint)
+{
+ /* Type constraints are printed out using background colors. */
+ static const char *colors[] = { "\x1b[31m", "\x1b[32m", "\x1b[33m",
+ "\x1b[34m", "\x1b[35m", "\x1b[36m",
+ "\x1b[37m" };
+ if (!InferSpewColorable())
+ return "";
+ return colors[DefaultHasher<TypeConstraint *>::hash(constraint) % 7];
+}
+
+const char *
+types::InferSpewColor(TypeSet *types)
+{
+ /* Type sets are printed out using bold colors. */
+ static const char *colors[] = { "\x1b[1;31m", "\x1b[1;32m", "\x1b[1;33m",
+ "\x1b[1;34m", "\x1b[1;35m", "\x1b[1;36m",
+ "\x1b[1;37m" };
+ if (!InferSpewColorable())
+ return "";
+ return colors[DefaultHasher<TypeSet *>::hash(types) % 7];
+}
+
+const char *
types::TypeString(jstype type)
{
switch (type) {
case TYPE_UNDEFINED:
return "void";
case TYPE_NULL:
return "null";
case TYPE_BOOLEAN:
@@ -301,17 +334,19 @@ TypeSet::make(JSContext *cx, const char
JS_ASSERT(cx->compartment->activeInference);
TypeSet *res = ArenaNew<TypeSet>(cx->compartment->pool);
if (!res) {
cx->compartment->types.setPendingNukeTypes(cx);
return NULL;
}
- InferSpew(ISpewOps, "typeSet: T%p intermediate %s", res, name);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s intermediate %s",
+ InferSpewColor(res), res, InferSpewColorReset(),
+ name);
res->setIntermediate();
return res;
}
void
TypeSet::addTypeSet(JSContext *cx, ClonedTypeSet *types)
{
@@ -342,18 +377,20 @@ TypeSet::add(JSContext *cx, TypeConstrai
return;
}
JS_ASSERT_IF(!constraint->condensed() && !constraint->persistentObject(),
constraint->script->compartment == cx->compartment);
JS_ASSERT_IF(!constraint->condensed(), cx->compartment->activeInference);
JS_ASSERT_IF(intermediate(), !constraint->persistentObject() && !constraint->condensed());
- InferSpew(ISpewOps, "addConstraint: T%p C%p %s",
- this, constraint, constraint->kind());
+ InferSpew(ISpewOps, "addConstraint: %sT%p%s %sC%p%s %s",
+ InferSpewColor(this), this, InferSpewColorReset(),
+ InferSpewColor(constraint), constraint, InferSpewColorReset(),
+ constraint->kind());
JS_ASSERT(constraint->next == NULL);
constraint->next = constraintList;
constraintList = constraint;
if (!callExisting)
return;
@@ -2208,18 +2245,20 @@ ScriptAnalysis::addTypeBarrier(JSContext
/* Ignore duplicate barriers. */
TypeBarrier *barrier = code.typeBarriers;
while (barrier) {
if (barrier->target == target && barrier->type == type)
return;
barrier = barrier->next;
}
- InferSpew(ISpewOps, "typeBarrier: #%u:%05u: T%p %s",
- script->id(), pc - script->code, target, TypeString(type));
+ InferSpew(ISpewOps, "typeBarrier: #%u:%05u: %sT%p%s %s",
+ script->id(), pc - script->code,
+ InferSpewColor(target), target, InferSpewColorReset(),
+ TypeString(type));
barrier = ArenaNew<TypeBarrier>(cx->compartment->pool);
barrier->target = target;
barrier->type = type;
barrier->next = code.typeBarriers;
code.typeBarriers = barrier;
}
@@ -2638,18 +2677,19 @@ TypeObject::addProperty(JSContext *cx, j
Property *base = cx->new_<Property>(id);
if (!base) {
cx->compartment->types.setPendingNukeTypes(cx);
return false;
}
*pprop = base;
- InferSpew(ISpewOps, "typeSet: T%p property %s %s",
- &base->types, name(), TypeIdString(id));
+ InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
+ InferSpewColor(&base->types), &base->types, InferSpewColorReset(),
+ name(), TypeIdString(id));
if (!JSID_IS_EMPTY(id)) {
/* Check all transitive instances for this property. */
if (instanceList)
storeToInstances(cx, base);
/* Pull in this property from all prototypes up the chain. */
getFromPrototypes(cx, base);
@@ -3124,25 +3164,28 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
/*
* The phi nodes at join points should all be unique, and every phi
* node created should be in the phiValues list on some bytecode.
*/
if (!state.phiNodes.append(newv->value.phiNode()))
return false;
TypeSet &types = newv->value.phiNode()->types;
types.setIntermediate();
- InferSpew(ISpewOps, "typeSet: T%p phi #%u:%05u:%u", &types,
+ InferSpew(ISpewOps, "typeSet: %sT%p%s phi #%u:%05u:%u",
+ InferSpewColor(&types), &types, InferSpewColorReset(),
script->id(), offset, newv->slot);
newv++;
}
}
for (unsigned i = 0; i < defCount; i++) {
pushed[i].setIntermediate();
- InferSpew(ISpewOps, "typeSet: T%p pushed%u #%u:%05u", &pushed[i], i, script->id(), offset);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s pushed%u #%u:%05u",
+ InferSpewColor(&pushed[i]), &pushed[i], InferSpewColorReset(),
+ i, script->id(), offset);
}
/* Add type constraints for the various opcodes. */
switch (op) {
/* Nop bytecodes. */
case JSOP_POP:
case JSOP_NOP:
@@ -5026,26 +5069,38 @@ TypeScript::makeTypeArray(JSContext *cx)
if (!typeArray) {
cx->compartment->types.setPendingNukeTypes(cx);
return false;
}
#ifdef DEBUG
unsigned id = script()->id();
for (unsigned i = 0; i < script()->nTypeSets; i++)
- InferSpew(ISpewOps, "typeSet: T%p bytecode%u #%u", &typeArray[i], i, id);
- InferSpew(ISpewOps, "typeSet: T%p return #%u", returnTypes(), id);
- InferSpew(ISpewOps, "typeSet: T%p this #%u", thisTypes(), id);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s bytecode%u #%u",
+ InferSpewColor(&typeArray[i]), &typeArray[i], InferSpewColorReset(),
+ i, id);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s return #%u",
+ InferSpewColor(returnTypes()), returnTypes(), InferSpewColorReset(),
+ id);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s this #%u",
+ InferSpewColor(thisTypes()), thisTypes(), InferSpewColorReset(),
+ id);
unsigned nargs = script()->fun ? script()->fun->nargs : 0;
for (unsigned i = 0; i < nargs; i++)
- InferSpew(ISpewOps, "typeSet: T%p arg%u #%u", argTypes(i), i, id);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s arg%u #%u",
+ InferSpewColor(argTypes(i)), argTypes(i), InferSpewColorReset(),
+ i, id);
for (unsigned i = 0; i < script()->nfixed; i++)
- InferSpew(ISpewOps, "typeSet: T%p local%u #%u", localTypes(i), i, id);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s local%u #%u",
+ InferSpewColor(localTypes(i)), localTypes(i), InferSpewColorReset(),
+ i, id);
for (unsigned i = 0; i < script()->bindings.countUpvars(); i++)
- InferSpew(ISpewOps, "typeSet: T%p upvar%u #%u", upvarTypes(i), i, id);
+ InferSpew(ISpewOps, "typeSet: %sT%p%s upvar%u #%u",
+ InferSpewColor(upvarTypes(i)), upvarTypes(i), InferSpewColorReset(),
+ i, id);
#endif
return true;
}
bool
JSScript::typeSetFunction(JSContext *cx, JSFunction *fun)
{
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -723,17 +723,19 @@ TypeScript::setUpvar(JSContext *cx, unsi
inline void
TypeCompartment::addPending(JSContext *cx, TypeConstraint *constraint, TypeSet *source, jstype type)
{
JS_ASSERT(this == &cx->compartment->types);
JS_ASSERT(type);
JS_ASSERT(!cx->runtime->gcRunning);
- InferSpew(ISpewOps, "pending: C%p %s", constraint, TypeString(type));
+ InferSpew(ISpewOps, "pending: %sC%p%s %s",
+ InferSpewColor(constraint), constraint, InferSpewColorReset(),
+ TypeString(type));
if (pendingCount == pendingCapacity)
growPendingArray(cx);
PendingWork &pending = pendingArray[pendingCount++];
pending.constraint = constraint;
pending.source = source;
pending.type = type;
@@ -749,18 +751,19 @@ TypeCompartment::resolvePending(JSContex
return;
}
resolving = true;
/* Handle all pending type registrations. */
while (pendingCount) {
const PendingWork &pending = pendingArray[--pendingCount];
- InferSpew(ISpewOps, "resolve: C%p %s",
- pending.constraint, TypeString(pending.type));
+ InferSpew(ISpewOps, "resolve: %sC%p%s %s",
+ InferSpewColor(pending.constraint), pending.constraint,
+ InferSpewColorReset(), TypeString(pending.type));
pending.constraint->newType(cx, pending.source, pending.type);
}
resolving = false;
}
/////////////////////////////////////////////////////////////////////
// TypeSet
@@ -1013,24 +1016,27 @@ TypeSet::addType(JSContext *cx, jstype t
(cx, objectSet, objectCount, object, intermediate());
if (!pentry || *pentry)
return;
*pentry = object;
if (objectCount > 1) {
object->contribution += (objectCount - 1) * (objectCount - 1);
if (object->contribution >= TypeObject::CONTRIBUTION_LIMIT) {
- InferSpew(ISpewOps, "limitUnknown: T%p", this);
+ InferSpew(ISpewOps, "limitUnknown: %sT%p%s",
+ InferSpewColor(this), this, InferSpewColorReset());
type = TYPE_UNKNOWN;
markUnknown(cx);
}
}
}
- InferSpew(ISpewOps, "addType: T%p %s", this, TypeString(type));
+ InferSpew(ISpewOps, "addType: %sT%p%s %s",
+ InferSpewColor(this), this, InferSpewColorReset(),
+ TypeString(type));
/* Propagate the type to all constraints. */
TypeConstraint *constraint = constraintList;
while (constraint) {
JS_ASSERT_IF(!constraint->persistentObject(),
constraint->script->compartment == cx->compartment);
cx->compartment->types.addPending(cx, constraint, this, type);
constraint = constraint->next;