[INFER] Remove guessing mechanism for unpacked arrays.

This commit is contained in:
Brian Hackett 2010-12-22 17:02:24 -08:00
parent 0424213572
commit f658ee07dd
5 changed files with 8 additions and 117 deletions

View File

@ -381,12 +381,6 @@ class Script
/* Any value pushed by a JSOP_DOUBLE. */
bool hasDouble;
double doubleValue;
/* Whether this is or could be the constant zero. */
bool isZero;
/* Whether this is another constant. */
bool isConstant;
};
struct AnalyzeState {
@ -401,13 +395,8 @@ class Script
/* Last opcode was JSOP_HOLE. */
bool hasHole;
/* Locals thought to be zero/constants. */
bool zeroLocals[4];
uint32 constLocals[4];
unsigned numConstLocals;
AnalyzeState()
: stack(NULL), stackDepth(0), hasGetSet(false), hasHole(false), numConstLocals(0)
: stack(NULL), stackDepth(0), hasGetSet(false), hasHole(false)
{}
bool init(JSContext *cx, JSScript *script)
@ -434,32 +423,6 @@ class Script
JS_ASSERT(i < stackDepth);
return stack[stackDepth - 1 - i];
}
void addConstLocal(uint32 local, bool zero) {
if (numConstLocals == JS_ARRAY_LENGTH(constLocals))
return;
if (maybeLocalConst(local, false))
return;
zeroLocals[numConstLocals] = zero;
constLocals[numConstLocals++] = local;
}
bool maybeLocalConst(uint32 local, bool zero) {
for (unsigned i = 0; i < numConstLocals; i++) {
if (constLocals[i] == local)
return !zero || zeroLocals[i];
}
return false;
}
void clearLocal(uint32 local) {
for (unsigned i = 0; i < numConstLocals; i++) {
if (constLocals[i] == local) {
constLocals[i] = constLocals[--numConstLocals];
return;
}
}
}
};
/* Analyzes a bytecode, generating type constraints describing its behavior. */

View File

@ -3399,7 +3399,6 @@ static void array_TypeNew(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *
if (site->argumentCount > 1) {
for (size_t ind = 0; ind < site->argumentCount; ind++)
site->argumentTypes[ind]->addSubset(cx, site->pool(), indexTypes);
object->possiblePackedArray = true;
}
#endif
}

View File

@ -1020,21 +1020,6 @@ TypeConstraintGenerator::newType(JSContext *cx, TypeSet *source, jstype type)
}
}
/* Constraint marking incoming arrays as possibly packed. */
class TypeConstraintPossiblyPacked : public TypeConstraint
{
public:
TypeConstraintPossiblyPacked() : TypeConstraint("possiblyPacked") {}
void newType(JSContext *cx, TypeSet *source, jstype type)
{
if (type != TYPE_UNKNOWN && TypeIsObject(type)) {
TypeObject *object = (TypeObject *) type;
object->possiblePackedArray = true;
}
}
};
/////////////////////////////////////////////////////////////////////
// Freeze constraints
/////////////////////////////////////////////////////////////////////
@ -1117,18 +1102,6 @@ TypeSet::getKnownTypeTag(JSContext *cx, JSScript *script)
static inline ObjectKind
CombineObjectKind(TypeObject *object, ObjectKind kind)
{
/*
* Our initial guess is that all arrays are packed, but if the array is
* created through [], Array() or Array(N) and we don't see later code
* which looks to be filling it in starting at zero, consider it not packed.
* All requests for the kind of an object go through here, so there are
* no FreezeObjectKind constraints to update if we unset isPackedArray here.
*/
if (object->isPackedArray && !object->possiblePackedArray) {
InferSpew(ISpewDynamic, "Possible unpacked array: %s", object->name());
object->isPackedArray = false;
}
ObjectKind nkind;
if (object->isFunction)
nkind = object->asFunction()->script ? OBJECT_SCRIPTED_FUNCTION : OBJECT_NATIVE_FUNCTION;
@ -2183,6 +2156,10 @@ CheckNextTest(JSContext *cx, Bytecode *code, jsbytecode *pc)
case JSOP_IFEQ:
case JSOP_IFNE:
case JSOP_NOT:
case JSOP_OR:
case JSOP_ORX:
case JSOP_AND:
case JSOP_ANDX:
case JSOP_TYPEOF:
case JSOP_TYPEOFEXPR:
code->pushed(0)->addType(cx, TYPE_UNDEFINED);
@ -2593,10 +2570,6 @@ Script::analyzeTypes(JSContext *cx, Bytecode *code, AnalyzeState &state)
}
if (op == JSOP_SETLOCAL || op == JSOP_SETLOCALPOP) {
state.clearLocal(local);
if (state.popped(0).isConstant)
state.addConstLocal(local, state.popped(0).isZero);
code->popped(0)->addSubset(cx, this->pool, types);
} else {
/*
@ -2619,8 +2592,6 @@ Script::analyzeTypes(JSContext *cx, Bytecode *code, AnalyzeState &state)
uint32 local = GET_SLOTNO(pc);
jsid id = getLocalId(local, code);
state.clearLocal(local);
TypeSet *types = evalParent()->getVariable(cx, id);
types->addArith(cx, evalParent()->pool, code, types);
MergePushed(cx, evalParent()->pool, code, 0, types);
@ -2721,18 +2692,6 @@ Script::analyzeTypes(JSContext *cx, Bytecode *code, AnalyzeState &state)
break;
case JSOP_SETELEM:
if (state.popped(1).isZero) {
/*
* Initializing the array with what looks like it could be zero.
* This is sensitive to the order in which bytecodes are emitted
* for common loop forms: '(for i = 0;; i++) a[i] = ...' and
* 'i = 0; while () { a[i] = ...; i++ }. In the bytecode the increment
* will appear after the initialization, and we are looking for arrays
* initialized between the two statements.
*/
code->popped(2)->add(cx, ArenaNew<TypeConstraintPossiblyPacked>(pool));
}
code->popped(1)->addSetElem(cx, code, code->popped(2), code->popped(0));
MergePushed(cx, pool, code, 0, code->popped(0));
break;
@ -2849,14 +2808,10 @@ Script::analyzeTypes(JSContext *cx, Bytecode *code, AnalyzeState &state)
case JSOP_NEWOBJECT:
if (script->compileAndGo) {
TypeObject *object;
if (op == JSOP_NEWARRAY || (op == JSOP_NEWINIT && pc[1] == JSProto_Array)) {
if (op == JSOP_NEWARRAY || (op == JSOP_NEWINIT && pc[1] == JSProto_Array))
object = code->initArray;
jsbytecode *next = pc + GetBytecodeLength(pc);
if (JSOp(*next) != JSOP_ENDINIT)
object->possiblePackedArray = true;
} else {
else
object = code->initObject;
}
code->pushed(0)->addType(cx, (jstype) object);
} else {
code->setFixed(cx, 0, TYPE_UNKNOWN);
@ -3201,25 +3156,6 @@ Script::analyzeTypes(JSContext *cx, Bytecode *code, AnalyzeState &state)
break;
}
case JSOP_ZERO:
state.popped(0).isZero = true;
/* FALLTHROUGH */
case JSOP_ONE:
case JSOP_INT8:
case JSOP_INT32:
case JSOP_UINT16:
case JSOP_UINT24:
state.popped(0).isConstant = true;
break;
case JSOP_GETLOCAL:
if (state.maybeLocalConst(GET_SLOTNO(pc), false)) {
state.popped(0).isConstant = true;
if (state.maybeLocalConst(GET_SLOTNO(pc), true))
state.popped(0).isZero = true;
}
break;
default:;
}
}

View File

@ -460,13 +460,6 @@ struct TypeObject
/* Whether all objects this represents are packed arrays (implies isDenseArray). */
bool isPackedArray;
/*
* Whether this object is thought to be a possible packed array: either it came
* from a [a,b,c] initializer, an Array(a,b,c) call, or is another array for
* which we've seen what looks like initialization code. This is purely heuristic.
*/
bool possiblePackedArray;
TypeObject() {}
/* Make an object with the specified name. */

View File

@ -1227,7 +1227,7 @@ inline TypeObject::TypeObject(JSArenaPool *pool, jsid name, JSObject *proto)
: proto(proto), emptyShapes(NULL), isFunction(false), marked(false),
propertySet(NULL), propertyCount(0),
instanceList(NULL), instanceNext(NULL), pool(pool), next(NULL), unknownProperties(false),
isDenseArray(false), isPackedArray(false), possiblePackedArray(false)
isDenseArray(false), isPackedArray(false)
{
#ifdef DEBUG
this->name_ = name;