mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[INFER] Fix inference freeze interface to directly reflect type information used by the Compiler.
This commit is contained in:
parent
545b668654
commit
631b2784ef
@ -309,12 +309,6 @@ class Script
|
||||
/* Array of local variable names, computed by js_GetLocalNameArray. */
|
||||
jsuword *localNames;
|
||||
|
||||
/* Whether this script is considered to be compiled, and types have been frozen. */
|
||||
bool compiled;
|
||||
|
||||
/* Whether this script needs recompilation. */
|
||||
bool recompileNeeded;
|
||||
|
||||
void setFunction(JSContext *cx, JSFunction *fun);
|
||||
|
||||
inline bool isEval() { return parent && !function; }
|
||||
@ -335,14 +329,6 @@ class Script
|
||||
/* Analyzes a bytecode, generating type constraints describing its behavior. */
|
||||
void analyzeTypes(JSContext *cx, Bytecode *codeType);
|
||||
|
||||
/*
|
||||
* Add new constraints for a bytecode monitoring changes on type sets which can
|
||||
* affect what the bytecode does. Performed after analysis has finished and the
|
||||
* type sets hopefully won't change further.
|
||||
*/
|
||||
void freezeTypes(JSContext *cx, Bytecode *codeType);
|
||||
void freezeAllTypes(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Get the name to use for the local with specified index. Stack indicates the
|
||||
* point of the access, for looking up let variables.
|
||||
|
@ -828,118 +828,50 @@ TypeConstraintMonitorRead::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Constraint which logs changes which occur after a script has been frozen,
|
||||
* at a bytecode granularity.
|
||||
* Constraint which triggers recompilation of a script if a possible new JSValueType
|
||||
* tag is realized for a type set.
|
||||
*/
|
||||
class TypeConstraintFreeze : public TypeConstraint
|
||||
class TypeConstraintFreezeTypeTag : public TypeConstraint
|
||||
{
|
||||
public:
|
||||
analyze::Bytecode *code;
|
||||
JSScript *script;
|
||||
bool isConstructing;
|
||||
|
||||
TypeConstraintFreeze(analyze::Bytecode *_code)
|
||||
: TypeConstraint("freeze"), code(_code)
|
||||
/*
|
||||
* Whether the type tag has been marked unknown due to a type change which
|
||||
* occurred after this constraint was generated (and which triggered recompilation).
|
||||
*/
|
||||
bool typeUnknown;
|
||||
|
||||
TypeConstraintFreezeTypeTag(JSScript *script, bool isConstructing)
|
||||
: TypeConstraint("freezeTypeTag"),
|
||||
script(script), isConstructing(isConstructing), typeUnknown(false)
|
||||
{}
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
{
|
||||
if (typeUnknown)
|
||||
return;
|
||||
|
||||
if (type != TYPE_UNKNOWN && TypeIsObject(type)) {
|
||||
/*
|
||||
* Ignore new objects when either (a) this is a non-function object
|
||||
* and there are already other known objects, or (b) this is a function
|
||||
* object and there were already at least two objects of any kind
|
||||
* (could not treat as a direct call). This can underapproximate the
|
||||
* number of recompilations actually required.
|
||||
*/
|
||||
TypeObject *obj = (TypeObject*) type;
|
||||
if (obj->isFunction) {
|
||||
if (source->objectCount >= 3)
|
||||
return;
|
||||
} else if (source->objectCount >= 2) {
|
||||
/* Ignore new objects when the type set already has other objects. */
|
||||
if (source->objectCount >= 2) {
|
||||
JS_ASSERT(source->typeFlags == TYPE_FLAG_OBJECT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cx->compartment->types.recompileScript(code);
|
||||
typeUnknown = true;
|
||||
|
||||
/* Need to trigger recompilation of the script here. :FIXME: bug 608746 */
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
TypeSet::addFreeze(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code)
|
||||
TypeSet::addFreezeTypeTag(JSContext *cx, JSScript *script, bool isConstructing)
|
||||
{
|
||||
JS_ASSERT(this->pool == &pool);
|
||||
add(cx, ArenaNew<TypeConstraintFreeze>(pool, code), false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constraint which logs changes to the types of a property of any object which
|
||||
* a type set can refer to.
|
||||
*/
|
||||
class TypeConstraintFreezeProp : public TypeConstraint
|
||||
{
|
||||
public:
|
||||
analyze::Bytecode *code;
|
||||
jsid id;
|
||||
|
||||
TypeConstraintFreezeProp(analyze::Bytecode *_code, jsid _id)
|
||||
: TypeConstraint("freezeprop"), code(_code), id(_id)
|
||||
{}
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
{
|
||||
if (type == TYPE_UNKNOWN)
|
||||
return;
|
||||
|
||||
TypeObject *object = GetPropertyObject(cx, type);
|
||||
if (!object)
|
||||
return;
|
||||
|
||||
TypeSet *types = object->properties(cx).getVariable(cx, id);
|
||||
types->addFreeze(cx, object->pool(), code);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
TypeSet::addFreezeProp(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code, jsid id)
|
||||
{
|
||||
JS_ASSERT(this->pool == &pool);
|
||||
add(cx, ArenaNew<TypeConstraintFreezeProp>(pool, code, id), false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constraint which logs changes to element accesses on an object, depending on
|
||||
* the type of the access.
|
||||
*/
|
||||
class TypeConstraintFreezeElem : public TypeConstraint
|
||||
{
|
||||
public:
|
||||
analyze::Bytecode *code;
|
||||
|
||||
/* Fields about the element access, as for TypeConstraintElem. */
|
||||
TypeSet *object;
|
||||
|
||||
TypeConstraintFreezeElem(analyze::Bytecode *code, TypeSet *object)
|
||||
: TypeConstraint("freezeelem"), code(code), object(object)
|
||||
{}
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
{
|
||||
if (type == TYPE_INT32) {
|
||||
object->addFreezeProp(cx, code->pool(), code, JSID_VOID);
|
||||
} else {
|
||||
/*
|
||||
* Accesses at this bytecode are monitored already, don't need
|
||||
* any freeze constraints.
|
||||
*/
|
||||
JS_ASSERT(code->monitorNeeded);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
TypeSet::addFreezeElem(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code, TypeSet *object)
|
||||
{
|
||||
JS_ASSERT(this->pool == &pool);
|
||||
add(cx, ArenaNew<TypeConstraintFreezeElem>(pool, code, object), false);
|
||||
JS_ASSERT(this->pool == &script->analysis->pool);
|
||||
add(cx, ArenaNew<TypeConstraintFreezeTypeTag>(script->analysis->pool, script, isConstructing), false);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -1170,8 +1102,6 @@ TypeCompartment::print(JSContext *cx, JSCompartment *compartment)
|
||||
}
|
||||
fprintf(out, " (%u over)\n", typeCountOver);
|
||||
|
||||
if (recompilations)
|
||||
fprintf(out, "Recompilations: %u\n", recompilations);
|
||||
fprintf(out, "Time: %.2f ms\n", millis);
|
||||
|
||||
// for debugging regressions.
|
||||
@ -1504,15 +1434,6 @@ JSScript::typeCheckBytecode(JSContext *cx, const jsbytecode *pc, const js::Value
|
||||
fputs("\n", cx->typeOut());
|
||||
#endif
|
||||
|
||||
if (!code.script->compiled)
|
||||
analysis->freezeAllTypes(cx);
|
||||
|
||||
if (code.script->recompileNeeded) {
|
||||
fprintf(cx->typeOut(), "Recompile: #%u\n", analysis->id);
|
||||
code.script->recompileNeeded = false;
|
||||
cx->compartment->types.recompilations++;
|
||||
}
|
||||
|
||||
if (!useCount || code.missingTypes)
|
||||
return;
|
||||
|
||||
@ -2749,191 +2670,6 @@ Script::analyzeTypes(JSContext *cx, Bytecode *code)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Script::freezeAllTypes(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!compiled);
|
||||
compiled = true;
|
||||
|
||||
unsigned offset = 0;
|
||||
while (offset < script->length) {
|
||||
Bytecode *code = codeArray[offset];
|
||||
|
||||
if (code && code->analyzed)
|
||||
freezeTypes(cx, code);
|
||||
|
||||
offset += GetBytecodeLength(script->code + offset);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Script::freezeTypes(JSContext *cx, Bytecode *code)
|
||||
{
|
||||
unsigned offset = code->offset;
|
||||
unsigned useCount = GetUseCount(script, offset);
|
||||
|
||||
JS_ASSERT(code->analyzed);
|
||||
jsbytecode *pc = script->code + offset;
|
||||
JSOp op = (JSOp)*pc;
|
||||
|
||||
switch (op) {
|
||||
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFEQX:
|
||||
case JSOP_IFNE:
|
||||
case JSOP_IFNEX:
|
||||
case JSOP_LOOKUPSWITCH:
|
||||
case JSOP_LOOKUPSWITCHX:
|
||||
case JSOP_TABLESWITCH:
|
||||
case JSOP_TABLESWITCHX:
|
||||
case JSOP_LSH:
|
||||
case JSOP_RSH:
|
||||
case JSOP_URSH:
|
||||
case JSOP_BITOR:
|
||||
case JSOP_BITXOR:
|
||||
case JSOP_BITAND:
|
||||
case JSOP_BITNOT:
|
||||
case JSOP_EQ:
|
||||
case JSOP_NE:
|
||||
case JSOP_LT:
|
||||
case JSOP_LE:
|
||||
case JSOP_GT:
|
||||
case JSOP_GE:
|
||||
case JSOP_NOT:
|
||||
case JSOP_STRICTEQ:
|
||||
case JSOP_STRICTNE:
|
||||
case JSOP_IN:
|
||||
case JSOP_DIV:
|
||||
case JSOP_OR:
|
||||
case JSOP_ORX:
|
||||
case JSOP_AND:
|
||||
case JSOP_ANDX:
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_GETXPROP:
|
||||
case JSOP_CALLPROP:
|
||||
case JSOP_GETELEM:
|
||||
case JSOP_CALLELEM:
|
||||
case JSOP_LENGTH:
|
||||
case JSOP_ADD:
|
||||
case JSOP_SUB:
|
||||
case JSOP_MUL:
|
||||
case JSOP_MOD:
|
||||
case JSOP_NEG:
|
||||
for (unsigned i = 0; i < useCount; i++)
|
||||
code->popped(i)->addFreeze(cx, pool, code);
|
||||
break;
|
||||
|
||||
case JSOP_INCNAME:
|
||||
case JSOP_DECNAME:
|
||||
case JSOP_NAMEINC:
|
||||
case JSOP_NAMEDEC: {
|
||||
jsid id = GetAtomId(cx, this, pc, 0);
|
||||
|
||||
VariableSet *vars = SearchScope(cx, this, code->inStack, id);
|
||||
if (vars) {
|
||||
TypeSet *types = vars->getVariable(cx, id);
|
||||
types->addFreeze(cx, *vars->pool, code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_INCGNAME:
|
||||
case JSOP_DECGNAME:
|
||||
case JSOP_GNAMEINC:
|
||||
case JSOP_GNAMEDEC: {
|
||||
jsid id = GetAtomId(cx, this, pc, 0);
|
||||
TypeSet *types = GetGlobalProperties(cx)->getVariable(cx, id);
|
||||
|
||||
types->addFreeze(cx, cx->compartment->types.pool, code);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_INCGLOBAL:
|
||||
case JSOP_DECGLOBAL:
|
||||
case JSOP_GLOBALINC:
|
||||
case JSOP_GLOBALDEC: {
|
||||
jsid id = GetGlobalId(cx, this, pc);
|
||||
TypeSet *types = GetGlobalProperties(cx)->getVariable(cx, id);
|
||||
|
||||
types->addFreeze(cx, cx->compartment->types.pool, code);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_INCARG:
|
||||
case JSOP_DECARG:
|
||||
case JSOP_ARGINC:
|
||||
case JSOP_ARGDEC:
|
||||
case JSOP_GETARGPROP: {
|
||||
jsid id = getArgumentId(GET_ARGNO(pc));
|
||||
TypeSet *types = localTypes.getVariable(cx, id);
|
||||
|
||||
types->addFreeze(cx, pool, code);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_INCLOCAL:
|
||||
case JSOP_DECLOCAL:
|
||||
case JSOP_LOCALINC:
|
||||
case JSOP_LOCALDEC:
|
||||
case JSOP_GETLOCALPROP: {
|
||||
jsid id = getLocalId(GET_SLOTNO(pc), code->inStack);
|
||||
TypeSet *types = evalParent()->localTypes.getVariable(cx, id);
|
||||
|
||||
types->addFreeze(cx, evalParent()->pool, code);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_SETPROP:
|
||||
case JSOP_SETMETHOD:
|
||||
code->popped(1)->addFreeze(cx, pool, code);
|
||||
break;
|
||||
|
||||
case JSOP_INCPROP:
|
||||
case JSOP_DECPROP:
|
||||
case JSOP_PROPINC:
|
||||
case JSOP_PROPDEC: {
|
||||
jsid id = GetAtomId(cx, this, pc, 0);
|
||||
code->popped(0)->addFreeze(cx, pool, code);
|
||||
code->popped(0)->addFreezeProp(cx, pool, code, id);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_GETTHISPROP:
|
||||
thisTypes.addFreeze(cx, pool, code);
|
||||
break;
|
||||
|
||||
case JSOP_SETELEM:
|
||||
code->popped(1)->addFreeze(cx, pool, code);
|
||||
code->popped(2)->addFreeze(cx, pool, code);
|
||||
break;
|
||||
|
||||
case JSOP_INCELEM:
|
||||
case JSOP_DECELEM:
|
||||
case JSOP_ELEMINC:
|
||||
case JSOP_ELEMDEC:
|
||||
code->popped(0)->addFreeze(cx, pool, code);
|
||||
code->popped(1)->addFreeze(cx, pool, code);
|
||||
code->popped(0)->addFreezeElem(cx, pool, code, code->popped(1));
|
||||
break;
|
||||
|
||||
case JSOP_CALL:
|
||||
case JSOP_EVAL:
|
||||
case JSOP_APPLY:
|
||||
case JSOP_NEW: {
|
||||
/*
|
||||
* The only value affecting the behavior of a call is the callee,
|
||||
* everything else is just copied around.
|
||||
*/
|
||||
TypeSet *funTypes = code->popped(useCount - 1);
|
||||
funTypes->addFreeze(cx, pool, code);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Printing
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -224,13 +224,15 @@ struct TypeSet
|
||||
void addFilterPrimitives(JSContext *cx, JSArenaPool &pool, TypeSet *target, bool onlyNullVoid);
|
||||
void addMonitorRead(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code, TypeSet *target);
|
||||
|
||||
/* For simulating recompilation. */
|
||||
void addFreeze(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code);
|
||||
void addFreezeProp(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code, jsid id);
|
||||
void addFreezeElem(JSContext *cx, JSArenaPool &pool, analyze::Bytecode *code, TypeSet *object);
|
||||
/* Constraints inducing recompilation. */
|
||||
void addFreezeTypeTag(JSContext *cx, JSScript *script, bool isConstructing);
|
||||
|
||||
/* Get any type tag which all values in this set must have. */
|
||||
inline JSValueType getKnownTypeTag();
|
||||
/*
|
||||
* Get any type tag which all values in this set must have. Should this type
|
||||
* set change in the future so that another type tag is possible, mark script
|
||||
* for recompilation.
|
||||
*/
|
||||
inline JSValueType getKnownTypeTag(JSContext *cx, JSScript *script, bool isConstructing);
|
||||
|
||||
/*
|
||||
* Make an intermediate type set with the specified debugging name,
|
||||
@ -719,9 +721,6 @@ struct TypeCompartment
|
||||
*/
|
||||
uint64_t analysisTime;
|
||||
|
||||
/* Number of times a script needed to be recompiled. */
|
||||
unsigned recompilations;
|
||||
|
||||
/* Counts of stack type sets with some number of possible operand types. */
|
||||
static const unsigned TYPE_COUNT_LIMIT = 4;
|
||||
unsigned typeCounts[TYPE_COUNT_LIMIT];
|
||||
@ -766,9 +765,6 @@ struct TypeCompartment
|
||||
|
||||
/* Monitor future effects on a bytecode. */
|
||||
inline void monitorBytecode(analyze::Bytecode *code);
|
||||
|
||||
/* Mark a bytecode's script as needing eventual recompilation. */
|
||||
inline void recompileScript(analyze::Bytecode *code);
|
||||
};
|
||||
|
||||
} /* namespace types */
|
||||
|
@ -838,27 +838,13 @@ TypeCompartment::resolvePending(JSContext *cx)
|
||||
resolving = false;
|
||||
}
|
||||
|
||||
inline void
|
||||
TypeCompartment::recompileScript(analyze::Bytecode *code)
|
||||
{
|
||||
JS_ASSERT(code->script->compiled);
|
||||
|
||||
if (!code->script->recompileNeeded) {
|
||||
#ifdef DEBUG
|
||||
fprintf(out, "MarkJIT: #%u:%05u\n", code->script->id, code->offset);
|
||||
#endif
|
||||
code->script->recompileNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
TypeCompartment::monitorBytecode(analyze::Bytecode *code)
|
||||
{
|
||||
if (code->monitorNeeded)
|
||||
return;
|
||||
|
||||
if (code->script->compiled)
|
||||
recompileScript(code);
|
||||
/* :FIXME: bug 608746 trigger recompilation of the script if necessary. */
|
||||
|
||||
#ifdef JS_TYPES_DEBUG_SPEW
|
||||
fprintf(out, "addMonitorNeeded: #%u:%05u\n", code->script->id, code->offset);
|
||||
@ -1134,24 +1120,36 @@ TypeSet::addType(JSContext *cx, jstype type)
|
||||
}
|
||||
|
||||
inline JSValueType
|
||||
TypeSet::getKnownTypeTag()
|
||||
TypeSet::getKnownTypeTag(JSContext *cx, JSScript *script, bool isConstructing)
|
||||
{
|
||||
JSValueType type;
|
||||
switch (typeFlags) {
|
||||
case TYPE_FLAG_UNDEFINED:
|
||||
return JSVAL_TYPE_UNDEFINED;
|
||||
type = JSVAL_TYPE_UNDEFINED;
|
||||
break;
|
||||
case TYPE_FLAG_NULL:
|
||||
return JSVAL_TYPE_NULL;
|
||||
type = JSVAL_TYPE_NULL;
|
||||
break;
|
||||
case TYPE_FLAG_BOOLEAN:
|
||||
return JSVAL_TYPE_BOOLEAN;
|
||||
type = JSVAL_TYPE_BOOLEAN;
|
||||
break;
|
||||
case TYPE_FLAG_INT32:
|
||||
return JSVAL_TYPE_INT32;
|
||||
type = JSVAL_TYPE_INT32;
|
||||
break;
|
||||
case TYPE_FLAG_STRING:
|
||||
return JSVAL_TYPE_STRING;
|
||||
type = JSVAL_TYPE_STRING;
|
||||
break;
|
||||
case TYPE_FLAG_OBJECT:
|
||||
return JSVAL_TYPE_OBJECT;
|
||||
type = JSVAL_TYPE_OBJECT;
|
||||
break;
|
||||
default:
|
||||
/* Return directly to avoid adding a type constraint. */
|
||||
return JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
addFreezeTypeTag(cx, script, isConstructing);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
inline TypeSet *
|
||||
|
@ -114,6 +114,10 @@ mjit::Compiler::Compiler(JSContext *cx, JSStackFrame *fp)
|
||||
#if defined JS_TRACER
|
||||
,addTraceHints(cx->traceJitEnabled)
|
||||
#endif
|
||||
#if defined JS_TYPE_INFERENCE
|
||||
,argumentTypes(ContextAllocPolicy(cx))
|
||||
,localTypes(ContextAllocPolicy(cx))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -158,16 +162,49 @@ mjit::Compiler::performCompilation(JITScript **jitp)
|
||||
JaegerSpew(JSpew_Scripts, "compiling script (file \"%s\") (line \"%d\") (length \"%d\")\n",
|
||||
script->filename, script->lineno, script->length);
|
||||
|
||||
uint32 nargs = fun ? fun->nargs : 0;
|
||||
if (!frame.init(nargs) || !stubcc.init(nargs))
|
||||
return Compile_Abort;
|
||||
|
||||
#ifdef JS_TYPE_INFERENCE
|
||||
this->analysis = script->analyze(cx);
|
||||
#else
|
||||
|
||||
/* Fill in known types of arguments and locals. */
|
||||
|
||||
if (!argumentTypes.reserve(nargs))
|
||||
return Compile_Error;
|
||||
for (unsigned i = 0; i < nargs; i++) {
|
||||
jsid id = analysis->getArgumentId(i);
|
||||
JSValueType type = JSVAL_TYPE_UNKNOWN;
|
||||
if (!JSID_IS_VOID(id)) {
|
||||
types::TypeSet *types = analysis->localTypes.getVariable(cx, id);
|
||||
type = types->getKnownTypeTag(cx, script, isConstructing);
|
||||
}
|
||||
argumentTypes.append(type);
|
||||
}
|
||||
|
||||
if (!localTypes.reserve(script->nfixed))
|
||||
return Compile_Error;
|
||||
for (unsigned i = 0; i < script->nfixed; i++) {
|
||||
jsid id = analysis->getLocalId(i, NULL);
|
||||
JSValueType type = JSVAL_TYPE_UNKNOWN;
|
||||
if (!analysis->localHasUseBeforeDef(i) && !JSID_IS_VOID(id)) {
|
||||
types::TypeSet *types = analysis->localTypes.getVariable(cx, id);
|
||||
type = types->getKnownTypeTag(cx, script, isConstructing);
|
||||
}
|
||||
localTypes.append(type);
|
||||
}
|
||||
|
||||
#else /* JS_TYPE_INFERENCE */
|
||||
|
||||
analyze::Script analysis_;
|
||||
PodZero(&analysis_);
|
||||
analysis_.init(script);
|
||||
analysis_.analyze(cx);
|
||||
|
||||
this->analysis = &analysis_;
|
||||
#endif
|
||||
|
||||
#endif /* JS_TYPE_INFERENCE */
|
||||
|
||||
if (analysis->OOM())
|
||||
return Compile_Error;
|
||||
@ -176,10 +213,6 @@ mjit::Compiler::performCompilation(JITScript **jitp)
|
||||
return Compile_Abort;
|
||||
}
|
||||
|
||||
uint32 nargs = fun ? fun->nargs : 0;
|
||||
if (!frame.init(nargs) || !stubcc.init(nargs))
|
||||
return Compile_Abort;
|
||||
|
||||
jumpMap = (Label *)cx->malloc(sizeof(Label) * script->length);
|
||||
if (!jumpMap)
|
||||
return Compile_Error;
|
||||
@ -4628,7 +4661,8 @@ mjit::Compiler::restoreAnalysisTypes(uint32 stackDepth)
|
||||
}
|
||||
for (uint32 i = 0; i < stackDepth; i++) {
|
||||
types::TypeStack *stack = analysis->getCode(PC).inStack;
|
||||
JSValueType type = analysis->getStackTypes(script->nfixed + i, stack)->getKnownTypeTag();
|
||||
types::TypeSet *types = analysis->getStackTypes(script->nfixed + i, stack);
|
||||
JSValueType type = types->getKnownTypeTag(cx, script, isConstructing);
|
||||
if (type != JSVAL_TYPE_UNKNOWN) {
|
||||
FrameEntry *fe = frame.getLocal(script->nfixed + i);
|
||||
frame.learnType(fe, type, true);
|
||||
@ -4641,9 +4675,8 @@ JSValueType
|
||||
mjit::Compiler::knownArgumentType(uint32 arg)
|
||||
{
|
||||
#ifdef JS_TYPE_INFERENCE
|
||||
jsid id = analysis->getArgumentId(arg);
|
||||
if (!JSID_IS_VOID(id))
|
||||
return analysis->localTypes.getVariable(cx, id)->getKnownTypeTag();
|
||||
JS_ASSERT(fun && arg < fun->nargs);
|
||||
return argumentTypes[arg];
|
||||
#endif
|
||||
return JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
@ -4652,9 +4685,8 @@ JSValueType
|
||||
mjit::Compiler::knownLocalType(uint32 local)
|
||||
{
|
||||
#ifdef JS_TYPE_INFERENCE
|
||||
jsid id = analysis->getLocalId(local, NULL);
|
||||
if (!analysis->localHasUseBeforeDef(local) && !JSID_IS_VOID(id))
|
||||
return analysis->localTypes.getVariable(cx, id)->getKnownTypeTag();
|
||||
JS_ASSERT(local < script->nfixed);
|
||||
return localTypes[local];
|
||||
#endif
|
||||
return JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
@ -4663,7 +4695,8 @@ JSValueType
|
||||
mjit::Compiler::knownPushedType(uint32 pushed)
|
||||
{
|
||||
#ifdef JS_TYPE_INFERENCE
|
||||
return analysis->getCode(PC).pushed(pushed)->getKnownTypeTag();
|
||||
types::TypeSet *types = analysis->getCode(PC).pushed(pushed);
|
||||
return types->getKnownTypeTag(cx, script, isConstructing);
|
||||
#endif
|
||||
return JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
@ -290,6 +290,11 @@ class Compiler : public BaseCompiler
|
||||
bool debugMode;
|
||||
bool addTraceHints;
|
||||
|
||||
#ifdef JS_TYPE_INFERENCE
|
||||
js::Vector<JSValueType, 16> argumentTypes;
|
||||
js::Vector<JSValueType, 16> localTypes;
|
||||
#endif
|
||||
|
||||
Compiler *thisFromCtor() { return this; }
|
||||
public:
|
||||
// Special atom index used to indicate that the atom is 'length'. This
|
||||
|
Loading…
Reference in New Issue
Block a user