[INFER] Decouple type sets computed by inference from analysis information, store in new TypeScript struct, bug 621301.

This commit is contained in:
Brian Hackett
2010-12-28 14:53:50 -05:00
parent a25161e6e8
commit 361372d7f2
31 changed files with 2049 additions and 2406 deletions

View File

@@ -2958,6 +2958,7 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
*vp = rval;
break;
case MAP:
cx->addTypePropertyId(newarr->getType(), JSID_VOID, rval);
ok = SetArrayElement(cx, newarr, i, rval);
if (!ok)
goto out;
@@ -2966,6 +2967,7 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
if (!cond)
break;
/* The element passed the filter, so push it onto our result. */
cx->addTypePropertyId(newarr->getType(), JSID_VOID, tvr.value());
ok = SetArrayElement(cx, newarr, newlen++, tvr.value());
if (!ok)
goto out;
@@ -3052,22 +3054,6 @@ static void array_TypeSort(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite
site->returnTypes->addType(cx, TYPE_UNKNOWN);
site->thisTypes->addSubset(cx, site->pool(), site->returnTypes);
}
if (site->argumentCount == 0)
return;
TypeSet *funTypes = site->argumentTypes[0];
/* Make a callsite for the calls to the sorting function this will perform. */
TypeCallsite *sortSite = ArenaNew<TypeCallsite>(site->pool(), site->code, false, 2);
sortSite->thisType = TYPE_UNDEFINED;
/* Both arguments to the argument function are array elements. */
TypeSet *argTypes = sortSite->argumentTypes[0] = sortSite->argumentTypes[1] =
TypeSet::make(cx, site->pool(), "ArraySort");
site->thisTypes->addGetProperty(cx, site->code, argTypes, JSID_VOID);
funTypes->addCall(cx, sortSite);
#endif
}
@@ -3085,8 +3071,10 @@ static void array_TypeInsert(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsit
site->forceThisTypes(cx);
for (size_t ind = 0; ind < site->argumentCount; ind++)
site->thisTypes->addSetProperty(cx, site->code, site->argumentTypes[ind], JSID_VOID);
for (size_t ind = 0; ind < site->argumentCount; ind++) {
site->thisTypes->addSetProperty(cx, site->script, site->pc,
site->argumentTypes[ind], JSID_VOID);
}
#endif
}
@@ -3102,7 +3090,7 @@ static void array_TypeRemove(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsit
site->returnTypes->addType(cx, TYPE_UNKNOWN);
site->forceThisTypes(cx);
site->thisTypes->addGetProperty(cx, site->code, site->returnTypes, JSID_VOID);
site->thisTypes->addGetProperty(cx, site->script, site->pc, site->returnTypes, JSID_VOID);
site->returnTypes->addType(cx, TYPE_UNDEFINED);
#endif
}
@@ -3122,8 +3110,10 @@ static void array_TypeSplice(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsit
}
/* All arguments beyond the first two are new array elements. */
for (size_t ind = 2; ind < site->argumentCount; ind++)
site->thisTypes->addSetProperty(cx, site->code, site->argumentTypes[ind], JSID_VOID);
for (size_t ind = 2; ind < site->argumentCount; ind++) {
site->thisTypes->addSetProperty(cx, site->script, site->pc,
site->argumentTypes[ind], JSID_VOID);
}
#endif
}
@@ -3151,11 +3141,13 @@ static void array_TypeConcat(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsit
/* Propagate elements of the 'this' array to the result. */
TypeSet *indexTypes = object->getProperty(cx, JSID_VOID, false);
site->thisTypes->addGetProperty(cx, site->code, indexTypes, JSID_VOID);
site->thisTypes->addGetProperty(cx, site->script, site->pc, indexTypes, JSID_VOID);
/* Ditto for all arguments to the call. */
for (size_t ind = 0; ind < site->argumentCount; ind++)
site->argumentTypes[ind]->addGetProperty(cx, site->code, indexTypes, JSID_VOID);
for (size_t ind = 0; ind < site->argumentCount; ind++) {
site->argumentTypes[ind]->addGetProperty(cx, site->script, site->pc,
indexTypes, JSID_VOID);
}
#endif
}
@@ -3165,86 +3157,28 @@ static void array_TypeExtra(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite
{
#ifdef JS_TYPE_INFERENCE
TypeCallsite *site = Valueify(jssite);
analyze::Bytecode *code = site->code;
JSArenaPool &pool = site->pool();
if (site->argumentCount == 0)
if (!site->returnTypes)
return;
TypeSet *funTypes = site->argumentTypes[0];
/*
* Get a type set of all possible element types of this array, and the singleton
* type of array indexes.
*/
TypeSet *elemTypes = TypeSet::make(cx, pool, "array_extra");
TypeSet *intTypes = TypeSet::make(cx, pool, "array_extra_int");
intTypes->addType(cx, TYPE_INT32);
site->forceThisTypes(cx);
site->forceReturnTypes(cx);
if (site->isNew)
site->returnTypes->addType(cx, TYPE_UNKNOWN);
site->thisTypes->addGetProperty(cx, code, elemTypes, JSID_VOID);
/* Make the call site to use for the higher order function. */
TypeCallsite *extraSite = ArenaNew<TypeCallsite>(pool, code, false, REDUCE_MODE(mode) ? 4 : 3);
/* Figure out the 'this' type passed to the higher order function. */
if (site->argumentCount > 1 && !REDUCE_MODE(mode))
extraSite->thisTypes = site->argumentTypes[1];
else
extraSite->thisType = TYPE_UNDEFINED;
switch (mode) {
case FOREACH:
site->returnTypes->addType(cx, TYPE_UNDEFINED);
break;
case REDUCE: {
/* The return value of the function is also the return value of the reduce call. */
extraSite->returnTypes = site->returnTypes;
/*
* The first argument of the function is either its own return value, the second
* argument of reduce, or the array element type (if there is no second argument
* of reduce).
*/
extraSite->argumentTypes[0] = TypeSet::make(cx, pool, "ArrayReduce");
site->returnTypes->addSubset(cx, pool, extraSite->argumentTypes[0]);
TypeSet *initialTypes = NULL;
if (site->argumentCount >= 2)
initialTypes = site->argumentTypes[1];
else
initialTypes = elemTypes;
initialTypes->addSubset(cx, pool, extraSite->argumentTypes[0]);
initialTypes->addSubset(cx, pool, site->returnTypes);
case REDUCE:
site->returnTypes->addType(cx, TYPE_UNKNOWN);
break;
}
case MAP:
if (site->compileAndGo()) {
/* Makes a new array whose element type is the return value of the argument function. */
TypeObject *object = site->getInitObject(cx, true);
extraSite->returnTypes = object->getProperty(cx, JSID_VOID, true);
site->returnTypes->addType(cx, (jstype) object);
} else {
site->returnTypes->addType(cx, TYPE_UNKNOWN);
}
break;
case FILTER:
if (site->compileAndGo()) {
/*
* Makes a new array, whose element type is the same as the element type
* of the 'this' array.
*/
/* Makes a new array whose element type will be filled in as the code runs. */
TypeObject *object = site->getInitObject(cx, true);
elemTypes->addSubset(cx, pool, object->getProperty(cx, JSID_VOID, true));
site->returnTypes->addType(cx, (jstype) object);
} else {
site->returnTypes->addType(cx, TYPE_UNKNOWN);
@@ -3258,18 +3192,6 @@ static void array_TypeExtra(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite
default:
JS_NOT_REACHED("Unexpected ArrayExtraMode");
}
/*
* Fill in the remaining argument types. regardless of mode, the last three
* arguments are the element value, element index, and array itself.
*/
size_t argind = (mode == REDUCE) ? 1 : 0;
extraSite->argumentTypes[argind++] = elemTypes;
extraSite->argumentTypes[argind++] = intTypes;
extraSite->argumentTypes[argind++] = site->thisTypes;
JS_ASSERT(argind == extraSite->argumentCount);
funTypes->addCall(cx, extraSite);
#endif
}