mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[INFER] Apply arguments and script review comments, bug 657412.
This commit is contained in:
parent
de9c3c81f6
commit
b0ae81df4a
@ -1023,7 +1023,7 @@ class ScriptAnalysis
|
||||
case SSAValue::VAR:
|
||||
JS_ASSERT(!slotEscapes(v.varSlot()));
|
||||
if (v.varInitial()) {
|
||||
return script->slotTypes(v.varSlot());
|
||||
return script->types.slotTypes(v.varSlot());
|
||||
} else {
|
||||
/*
|
||||
* Results of intermediate assignments have the same type as
|
||||
|
@ -4302,7 +4302,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
||||
Value v;
|
||||
if (!obj->getProperty(cx, r.front().propid, &v))
|
||||
return NULL;
|
||||
fun->script()->typeSetUpvar(cx, i, v);
|
||||
fun->script()->types.setUpvar(cx, i, v);
|
||||
clone->getFlatClosureUpvars()[i] = v;
|
||||
}
|
||||
|
||||
|
@ -3241,7 +3241,7 @@ array_TypeConcat(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
|
||||
{
|
||||
TypeCallsite *site = Valueify(jssite);
|
||||
|
||||
if (!site->hasGlobal()) {
|
||||
if (!site->script->hasGlobal()) {
|
||||
site->returnTypes->addType(cx, TYPE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
@ -3283,7 +3283,7 @@ array_TypeExtra(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite,
|
||||
|
||||
case MAP:
|
||||
case FILTER:
|
||||
if (site->hasGlobal()) {
|
||||
if (site->script->hasGlobal()) {
|
||||
/* Makes a new array whose element type will be filled in as the code runs. */
|
||||
TypeObject *object = site->getInitObject(cx, true);
|
||||
if (!object)
|
||||
@ -3434,7 +3434,7 @@ array_TypeNew(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
|
||||
{
|
||||
TypeCallsite *site = Valueify(jssite);
|
||||
|
||||
if (!site->hasGlobal()) {
|
||||
if (!site->script->hasGlobal()) {
|
||||
site->returnTypes->addType(cx, TYPE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
|
||||
for (JSCList *cursor = scripts.next; ok && cursor != &scripts; cursor = cursor->next) {
|
||||
JSScript *script = reinterpret_cast<JSScript *>(cursor);
|
||||
ok = script->condenseTypes(cx);
|
||||
ok = script->types.condenseTypes(cx);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
|
@ -223,12 +223,6 @@ JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
|
||||
mjit::ReleaseScriptCode(cx, script, true);
|
||||
mjit::ReleaseScriptCode(cx, script, false);
|
||||
script->debugMode = !!debug;
|
||||
|
||||
/* Mark arguments objects as escaping in all scripts if debug mode is on. */
|
||||
if (script->usesArguments && debug) {
|
||||
types::MarkTypeObjectFlags(cx, script->fun->getType(),
|
||||
types::OBJECT_FLAG_CREATED_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2821,7 +2821,10 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
|
||||
op = JSOP_CALLPROP;
|
||||
} else if (op == JSOP_GETPROP && pn->pn_type == TOK_DOT) {
|
||||
if (pn2->pn_type == TOK_NAME) {
|
||||
/* Try to optimize arguments.length into JSOP_ARGCNT */
|
||||
/*
|
||||
* Try to optimize arguments.length into JSOP_ARGCNT. If type
|
||||
* inference is enabled this is optimized separately.
|
||||
*/
|
||||
if (!BindNameToSlot(cx, cg, pn2))
|
||||
return JS_FALSE;
|
||||
if (!cx->typeInferenceEnabled() &&
|
||||
@ -2909,7 +2912,8 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
||||
|
||||
/*
|
||||
* Try to optimize arguments[0][j]... into JSOP_ARGSUB<0> followed by
|
||||
* one or more index expression and JSOP_GETELEM op pairs.
|
||||
* one or more index expression and JSOP_GETELEM op pairs. If type
|
||||
* inference is enabled this is optimized separately.
|
||||
*/
|
||||
if (left->pn_type == TOK_NAME && next->pn_type == TOK_NUMBER) {
|
||||
if (!BindNameToSlot(cx, cg, left))
|
||||
@ -2985,7 +2989,10 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
||||
right = pn->pn_right;
|
||||
}
|
||||
|
||||
/* Try to optimize arguments[0] (e.g.) into JSOP_ARGSUB<0>. */
|
||||
/*
|
||||
* Try to optimize arguments[0] (e.g.) into JSOP_ARGSUB<0>. If type
|
||||
* inference is enabled this is optimized separately.
|
||||
*/
|
||||
if (op == JSOP_GETELEM &&
|
||||
left->pn_type == TOK_NAME &&
|
||||
right->pn_type == TOK_NUMBER) {
|
||||
|
@ -108,10 +108,6 @@ JSBool
|
||||
js_GetArgsValue(JSContext *cx, StackFrame *fp, Value *vp)
|
||||
{
|
||||
JSObject *argsobj;
|
||||
|
||||
MarkTypeObjectFlags(cx, fp->fun()->getType(),
|
||||
OBJECT_FLAG_CREATED_ARGUMENTS | OBJECT_FLAG_UNINLINEABLE);
|
||||
|
||||
if (fp->hasOverriddenArgs()) {
|
||||
JS_ASSERT(fp->hasCallObj());
|
||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom);
|
||||
@ -256,6 +252,13 @@ js_GetArgsObject(JSContext *cx, StackFrame *fp)
|
||||
*/
|
||||
JS_ASSERT_IF(fp->fun()->isHeavyweight(), fp->hasCallObj());
|
||||
|
||||
/*
|
||||
* Mark all functions which have ever had arguments objects constructed,
|
||||
* which will prevent lazy arguments optimizations in the method JIT.
|
||||
*/
|
||||
MarkTypeObjectFlags(cx, fp->fun()->getType(),
|
||||
OBJECT_FLAG_CREATED_ARGUMENTS | OBJECT_FLAG_UNINLINEABLE);
|
||||
|
||||
while (fp->isDirectEvalOrDebuggerFrame())
|
||||
fp = fp->prev();
|
||||
|
||||
@ -599,7 +602,7 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
JSScript *script = fp->functionScript();
|
||||
if (script->usesArguments) {
|
||||
if (arg < fp->numFormalArgs())
|
||||
script->typeSetArgument(cx, arg, *vp);
|
||||
script->types.setArgument(cx, arg, *vp);
|
||||
fp->canonicalActualArg(arg) = *vp;
|
||||
}
|
||||
return true;
|
||||
@ -1245,7 +1248,7 @@ SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
argp = &obj->callObjArg(i);
|
||||
|
||||
JSScript *script = obj->getCallObjCalleeFunction()->script();
|
||||
script->typeSetArgument(cx, i, *vp);
|
||||
script->types.setArgument(cx, i, *vp);
|
||||
|
||||
GCPoke(cx, *argp);
|
||||
*argp = *vp;
|
||||
@ -1328,7 +1331,7 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
varp = &obj->callObjVar(i);
|
||||
|
||||
JSScript *script = obj->getCallObjCalleeFunction()->script();
|
||||
script->typeSetLocal(cx, i, *vp);
|
||||
script->types.setLocal(cx, i, *vp);
|
||||
|
||||
GCPoke(cx, *varp);
|
||||
*varp = *vp;
|
||||
@ -2981,7 +2984,7 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen)
|
||||
|
||||
for (uint32 i = 0, n = uva->length; i < n; i++) {
|
||||
upvars[i] = GetUpvar(cx, level, uva->vector[i]);
|
||||
fun->script()->typeSetUpvar(cx, i, upvars[i]);
|
||||
fun->script()->types.setUpvar(cx, i, upvars[i]);
|
||||
}
|
||||
|
||||
return closure;
|
||||
|
@ -914,15 +914,15 @@ GetPropertyObject(JSContext *cx, JSScript *script, jstype type)
|
||||
|
||||
case TYPE_INT32:
|
||||
case TYPE_DOUBLE:
|
||||
object = script->getTypeNewObject(cx, JSProto_Number);
|
||||
object = script->types.standardType(cx, JSProto_Number);
|
||||
break;
|
||||
|
||||
case TYPE_BOOLEAN:
|
||||
object = script->getTypeNewObject(cx, JSProto_Boolean);
|
||||
object = script->types.standardType(cx, JSProto_Boolean);
|
||||
break;
|
||||
|
||||
case TYPE_STRING:
|
||||
object = script->getTypeNewObject(cx, JSProto_String);
|
||||
object = script->types.standardType(cx, JSProto_String);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1001,7 +1001,7 @@ TypeConstraintProp::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
{
|
||||
UntrapOpcode untrap(cx, script, pc);
|
||||
|
||||
if (type == TYPE_UNKNOWN || (!TypeIsObject(type) && !script->global)) {
|
||||
if (type == TYPE_UNKNOWN || (!TypeIsObject(type) && !script->hasGlobal())) {
|
||||
/*
|
||||
* Access on an unknown object. Reads produce an unknown result, writes
|
||||
* need to be monitored. Note: this isn't a problem for handling overflows
|
||||
@ -1044,7 +1044,7 @@ TypeConstraintCallProp::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
* get their 'this' types updated.
|
||||
*/
|
||||
|
||||
if (type == TYPE_UNKNOWN || (!TypeIsObject(type) && !script->global)) {
|
||||
if (type == TYPE_UNKNOWN || (!TypeIsObject(type) && !script->hasGlobal())) {
|
||||
cx->compartment->types.monitorBytecode(cx, script, callpc - script->code);
|
||||
return;
|
||||
}
|
||||
@ -1088,10 +1088,10 @@ TypeConstraintNewObject::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
* native constructors with immutable non-primitive prototypes.
|
||||
* Disregard primitives here.
|
||||
*/
|
||||
} else if (!fun->script->global) {
|
||||
} else if (!fun->script->hasGlobal()) {
|
||||
target->addType(cx, TYPE_UNKNOWN);
|
||||
} else {
|
||||
TypeObject *object = fun->script->getTypeNewObject(cx, JSProto_Object);
|
||||
TypeObject *object = fun->script->types.standardType(cx, JSProto_Object);
|
||||
if (!object) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
@ -1140,7 +1140,7 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
* :FIXME: bug 631135. Rather than try to model this, just mark the
|
||||
* result of cross-global native calls as unknown.
|
||||
*/
|
||||
if (!script->global || script->global != function->singleton->getGlobal()) {
|
||||
if (!script->hasGlobal() || script->global() != function->singleton->getGlobal()) {
|
||||
callsite->returnTypes->addType(cx, TYPE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
@ -1187,42 +1187,38 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
JSScript *callee = function->script;
|
||||
unsigned nargs = callee->fun->nargs;
|
||||
|
||||
if (!callee->ensureTypeArray(cx))
|
||||
if (!callee->types.ensureTypeArray(cx))
|
||||
return;
|
||||
|
||||
/* Analyze the function if we have not already done so. */
|
||||
if (!callee->ranInference) {
|
||||
ScriptAnalysis *calleeAnalysis = callee->analysis(cx);
|
||||
if (!calleeAnalysis) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
calleeAnalysis->analyzeTypes(cx);
|
||||
if (!callee->ensureRanInference(cx)) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add bindings for the arguments of the call. */
|
||||
for (unsigned i = 0; i < callsite->argumentCount && i < nargs; i++) {
|
||||
TypeSet *argTypes = callsite->argumentTypes[i];
|
||||
TypeSet *types = callee->argTypes(i);
|
||||
TypeSet *types = callee->types.argTypes(i);
|
||||
argTypes->addSubsetBarrier(cx, script, pc, types);
|
||||
}
|
||||
|
||||
/* Add void type for any formals in the callee not supplied at the call site. */
|
||||
for (unsigned i = callsite->argumentCount; i < nargs; i++) {
|
||||
TypeSet *types = callee->argTypes(i);
|
||||
TypeSet *types = callee->types.argTypes(i);
|
||||
types->addType(cx, TYPE_UNDEFINED);
|
||||
}
|
||||
|
||||
if (callsite->isNew) {
|
||||
/* Mark the callee as having been invoked with 'new'. */
|
||||
callee->typeSetNewCalled(cx);
|
||||
callee->types.setNewCalled(cx);
|
||||
|
||||
/*
|
||||
* If the script does not return a value then the pushed value is the new
|
||||
* object (typical case).
|
||||
*/
|
||||
callee->thisTypes()->addSubset(cx, script, callsite->returnTypes);
|
||||
callee->returnTypes()->addFilterPrimitives(cx, script, callsite->returnTypes, false);
|
||||
callee->types.thisTypes()->addSubset(cx, script, callsite->returnTypes);
|
||||
callee->types.returnTypes()->addFilterPrimitives(cx, script, callsite->returnTypes, false);
|
||||
} else {
|
||||
/*
|
||||
* Add a binding for the return value of the call. We don't add a
|
||||
@ -1232,7 +1228,7 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
* in the 'this' and 'callee' sets, which we want to maintain for
|
||||
* polymorphic JSOP_CALLPROP invocations.
|
||||
*/
|
||||
callee->returnTypes()->addSubset(cx, script, callsite->returnTypes);
|
||||
callee->types.returnTypes()->addSubset(cx, script, callsite->returnTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1265,10 +1261,10 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, jstype type
|
||||
|
||||
JSScript *callee = function->script;
|
||||
|
||||
if (!callee->ensureTypeArray(cx))
|
||||
if (!callee->types.ensureTypeArray(cx))
|
||||
return;
|
||||
|
||||
callee->thisTypes()->addType(cx, this->type);
|
||||
callee->types.thisTypes()->addType(cx, this->type);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1342,7 +1338,7 @@ TypeConstraintTransformThis::newType(JSContext *cx, TypeSet *source, jstype type
|
||||
* Note: if |this| is null or undefined, the pushed value is the outer window. We
|
||||
* can't use script->getGlobalType() here because it refers to the inner window.
|
||||
*/
|
||||
if (!script->global || type == TYPE_NULL || type == TYPE_UNDEFINED) {
|
||||
if (!script->hasGlobal() || type == TYPE_NULL || type == TYPE_UNDEFINED) {
|
||||
target->addType(cx, TYPE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
@ -1351,13 +1347,13 @@ TypeConstraintTransformThis::newType(JSContext *cx, TypeSet *source, jstype type
|
||||
switch (type) {
|
||||
case TYPE_INT32:
|
||||
case TYPE_DOUBLE:
|
||||
object = script->getTypeNewObject(cx, JSProto_Number);
|
||||
object = script->types.standardType(cx, JSProto_Number);
|
||||
break;
|
||||
case TYPE_BOOLEAN:
|
||||
object = script->getTypeNewObject(cx, JSProto_Boolean);
|
||||
object = script->types.standardType(cx, JSProto_Boolean);
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
object = script->getTypeNewObject(cx, JSProto_String);
|
||||
object = script->types.standardType(cx, JSProto_String);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -1675,7 +1671,6 @@ FixLazyArguments(JSContext *cx, JSScript *script)
|
||||
mjit::ExpandInlineFrames(cx, FRAME_EXPAND_ALL);
|
||||
#endif
|
||||
|
||||
/* :FIXME: handle OOM at calls here. */
|
||||
ScriptAnalysis *analysis = script->analysis(cx);
|
||||
if (analysis && !analysis->ranBytecode())
|
||||
analysis->analyzeBytecode(cx);
|
||||
@ -1696,9 +1691,8 @@ FixLazyArguments(JSContext *cx, JSScript *script)
|
||||
Value *sp = fp->base() + analysis->getCode(pc).stackDepth;
|
||||
for (Value *vp = fp->slots(); vp < sp; vp++) {
|
||||
if (vp->isMagicCheck(JS_LAZY_ARGUMENTS)) {
|
||||
if (!js_GetArgsValue(cx, fp, vp)) {
|
||||
/* FIXME */
|
||||
}
|
||||
if (!js_GetArgsValue(cx, fp, vp))
|
||||
vp->setNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1881,7 +1875,7 @@ TypeCompartment::newTypeObject(JSContext *cx, JSScript *script,
|
||||
if (!object)
|
||||
return NULL;
|
||||
|
||||
TypeObject *&objects = script ? script->typeObjects : this->objects;
|
||||
TypeObject *&objects = script ? script->types.typeObjects : this->objects;
|
||||
object->next = objects;
|
||||
objects = object;
|
||||
|
||||
@ -1914,7 +1908,7 @@ TypeCompartment::newInitializerTypeObject(JSContext *cx, JSScript *script,
|
||||
|
||||
JSObject *proto;
|
||||
JSProtoKey key = isArray ? JSProto_Array : JSProto_Object;
|
||||
if (!js_GetClassPrototype(cx, script->getGlobal(), key, &proto, NULL))
|
||||
if (!js_GetClassPrototype(cx, script->global(), key, &proto, NULL))
|
||||
return NULL;
|
||||
|
||||
TypeObject *res = newTypeObject(cx, script, name, "", false, isArray, proto);
|
||||
@ -2266,7 +2260,7 @@ TypeCompartment::print(JSContext *cx, JSCompartment *compartment)
|
||||
script = (JSScript *)script->links.next) {
|
||||
if (script->hasAnalysis() && script->analysis(cx)->ranInference())
|
||||
script->analysis(cx)->printTypes(cx);
|
||||
TypeObject *object = script->typeObjects;
|
||||
TypeObject *object = script->types.typeObjects;
|
||||
while (object) {
|
||||
object->print(cx);
|
||||
object = object->next;
|
||||
@ -3088,7 +3082,7 @@ CheckNextTest(jsbytecode *pc)
|
||||
static inline TypeObject *
|
||||
GetInitializerType(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
if (!script->global)
|
||||
if (!script->hasGlobal())
|
||||
return NULL;
|
||||
|
||||
UntrapOpcode untrap(cx, script, pc);
|
||||
@ -3097,7 +3091,7 @@ GetInitializerType(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
JS_ASSERT(op == JSOP_NEWARRAY || op == JSOP_NEWOBJECT || op == JSOP_NEWINIT);
|
||||
|
||||
bool isArray = (op == JSOP_NEWARRAY || (op == JSOP_NEWINIT && pc[1] == JSProto_Array));
|
||||
return script->getTypeInitObject(cx, pc, isArray);
|
||||
return script->types.initObject(cx, pc, isArray);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -3292,8 +3286,8 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
break;
|
||||
|
||||
case JSOP_REGEXP:
|
||||
if (script->global) {
|
||||
TypeObject *object = script->getTypeNewObject(cx, JSProto_RegExp);
|
||||
if (script->hasGlobal()) {
|
||||
TypeObject *object = script->types.standardType(cx, JSProto_RegExp);
|
||||
if (!object)
|
||||
return false;
|
||||
pushed[0].addType(cx, (jstype) object);
|
||||
@ -3311,7 +3305,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_STOP:
|
||||
/* If a stop is reachable then the return type may be void. */
|
||||
if (script->fun)
|
||||
script->returnTypes()->addType(cx, TYPE_UNDEFINED);
|
||||
script->types.returnTypes()->addType(cx, TYPE_UNDEFINED);
|
||||
break;
|
||||
|
||||
case JSOP_OR:
|
||||
@ -3344,7 +3338,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
else
|
||||
id = GetAtomId(cx, script, pc, 0);
|
||||
|
||||
TypeSet *seen = script->bytecodeTypes(pc);
|
||||
TypeSet *seen = script->types.bytecodeTypes(pc);
|
||||
seen->addSubset(cx, script, &pushed[0]);
|
||||
|
||||
/*
|
||||
@ -3360,7 +3354,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
seen->addType(cx, TYPE_DOUBLE);
|
||||
|
||||
/* Handle as a property access. */
|
||||
PropertyAccess(cx, script, pc, script->getGlobalType(), false, seen, id);
|
||||
PropertyAccess(cx, script, pc, script->global()->getType(), false, seen, id);
|
||||
|
||||
if (op == JSOP_CALLGLOBAL || op == JSOP_CALLGNAME) {
|
||||
pushed[1].addType(cx, TYPE_UNKNOWN);
|
||||
@ -3384,8 +3378,8 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_GNAMEINC:
|
||||
case JSOP_GNAMEDEC: {
|
||||
jsid id = GetAtomId(cx, script, pc, 0);
|
||||
PropertyAccess(cx, script, pc, script->getGlobalType(), true, NULL, id);
|
||||
PropertyAccess(cx, script, pc, script->getGlobalType(), false, &pushed[0], id);
|
||||
PropertyAccess(cx, script, pc, script->global()->getType(), true, NULL, id);
|
||||
PropertyAccess(cx, script, pc, script->global()->getType(), false, &pushed[0], id);
|
||||
|
||||
if (cx->compartment->debugMode)
|
||||
pushed[0].addType(cx, TYPE_UNKNOWN);
|
||||
@ -3398,7 +3392,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
* The first value pushed by NAME/CALLNAME must always be added to the
|
||||
* bytecode types, we don't model these opcodes with inference.
|
||||
*/
|
||||
TypeSet *seen = script->bytecodeTypes(pc);
|
||||
TypeSet *seen = script->types.bytecodeTypes(pc);
|
||||
seen->addSubset(cx, script, &pushed[0]);
|
||||
if (op == JSOP_CALLNAME) {
|
||||
pushed[1].addType(cx, TYPE_UNKNOWN);
|
||||
@ -3413,7 +3407,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
|
||||
case JSOP_SETGNAME: {
|
||||
jsid id = GetAtomId(cx, script, pc, 0);
|
||||
PropertyAccess(cx, script, pc, script->getGlobalType(),
|
||||
PropertyAccess(cx, script, pc, script->global()->getType(),
|
||||
true, poppedTypes(pc, 0), id);
|
||||
poppedTypes(pc, 0)->addSubset(cx, script, &pushed[0]);
|
||||
break;
|
||||
@ -3433,7 +3427,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
break;
|
||||
|
||||
case JSOP_GETXPROP: {
|
||||
TypeSet *seen = script->bytecodeTypes(pc);
|
||||
TypeSet *seen = script->types.bytecodeTypes(pc);
|
||||
seen->addSubset(cx, script, &pushed[0]);
|
||||
break;
|
||||
}
|
||||
@ -3441,7 +3435,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_GETFCSLOT:
|
||||
case JSOP_CALLFCSLOT: {
|
||||
unsigned index = GET_UINT16(pc);
|
||||
TypeSet *types = script->upvarTypes(index);
|
||||
TypeSet *types = script->types.upvarTypes(index);
|
||||
types->addSubset(cx, script, &pushed[0]);
|
||||
if (op == JSOP_CALLFCSLOT) {
|
||||
pushed[1].addType(cx, TYPE_UNDEFINED);
|
||||
@ -3472,7 +3466,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
*/
|
||||
poppedTypes(pc, 0)->addSubset(cx, script, &pushed[0]);
|
||||
} else if (slot < TotalSlots(script)) {
|
||||
TypeSet *types = script->slotTypes(slot);
|
||||
TypeSet *types = script->types.slotTypes(slot);
|
||||
types->addSubset(cx, script, &pushed[0]);
|
||||
} else {
|
||||
/* Local 'let' variable. Punt on types for these, for now. */
|
||||
@ -3490,7 +3484,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_SETLOCALPOP: {
|
||||
uint32 slot = GetBytecodeSlot(script, pc);
|
||||
if (!trackSlot(slot) && slot < TotalSlots(script)) {
|
||||
TypeSet *types = script->slotTypes(slot);
|
||||
TypeSet *types = script->types.slotTypes(slot);
|
||||
poppedTypes(pc, 0)->addSubset(cx, script, types);
|
||||
}
|
||||
|
||||
@ -3515,7 +3509,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
if (trackSlot(slot)) {
|
||||
poppedTypes(pc, 0)->addArith(cx, script, &pushed[0]);
|
||||
} else if (slot < TotalSlots(script)) {
|
||||
TypeSet *types = script->slotTypes(slot);
|
||||
TypeSet *types = script->types.slotTypes(slot);
|
||||
types->addArith(cx, script, types);
|
||||
types->addSubset(cx, script, &pushed[0]);
|
||||
} else {
|
||||
@ -3551,7 +3545,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_CALLPROP: {
|
||||
jsid id = GetAtomId(cx, script, pc, 0);
|
||||
TypeSet *seen = script->bytecodeTypes(pc);
|
||||
TypeSet *seen = script->types.bytecodeTypes(pc);
|
||||
|
||||
poppedTypes(pc, 0)->addGetProperty(cx, script, pc, seen, id);
|
||||
if (op == JSOP_CALLPROP)
|
||||
@ -3581,7 +3575,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
|
||||
case JSOP_GETELEM:
|
||||
case JSOP_CALLELEM: {
|
||||
TypeSet *seen = script->bytecodeTypes(pc);
|
||||
TypeSet *seen = script->types.bytecodeTypes(pc);
|
||||
|
||||
poppedTypes(pc, 1)->addGetProperty(cx, script, pc, seen, JSID_VOID);
|
||||
if (op == JSOP_CALLELEM)
|
||||
@ -3609,13 +3603,13 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
break;
|
||||
|
||||
case JSOP_THIS:
|
||||
script->thisTypes()->addTransformThis(cx, script, &pushed[0]);
|
||||
script->types.thisTypes()->addTransformThis(cx, script, &pushed[0]);
|
||||
break;
|
||||
|
||||
case JSOP_RETURN:
|
||||
case JSOP_SETRVAL:
|
||||
if (script->fun)
|
||||
poppedTypes(pc, 0)->addSubset(cx, script, script->returnTypes());
|
||||
poppedTypes(pc, 0)->addSubset(cx, script, script->types.returnTypes());
|
||||
break;
|
||||
|
||||
case JSOP_ADD:
|
||||
@ -3655,12 +3649,12 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
} else {
|
||||
/* Should not see 'let' vars here. */
|
||||
JS_ASSERT(slot < TotalSlots(script));
|
||||
res = script->slotTypes(slot);
|
||||
res = script->types.slotTypes(slot);
|
||||
}
|
||||
}
|
||||
|
||||
if (res) {
|
||||
if (script->global)
|
||||
if (script->hasGlobal())
|
||||
res->addType(cx, (jstype) obj->getType());
|
||||
else
|
||||
res->addType(cx, TYPE_UNKNOWN);
|
||||
@ -3708,7 +3702,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
case JSOP_NEWARRAY:
|
||||
case JSOP_NEWOBJECT: {
|
||||
TypeObject *initializer = GetInitializerType(cx, script, pc);
|
||||
if (script->global) {
|
||||
if (script->hasGlobal()) {
|
||||
if (!initializer)
|
||||
return false;
|
||||
pushed[0].addType(cx, (jstype) initializer);
|
||||
@ -3816,7 +3810,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
|
||||
case JSOP_FORGNAME: {
|
||||
jsid id = GetAtomId(cx, script, pc, 0);
|
||||
TypeObject *global = script->getGlobalType();
|
||||
TypeObject *global = script->global()->getType();
|
||||
if (!global->unknownProperties()) {
|
||||
TypeSet *types = global->getProperty(cx, id, true);
|
||||
if (!types)
|
||||
@ -3837,7 +3831,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
setForTypes(cx, pc, &pushed[1]);
|
||||
} else {
|
||||
if (slot < TotalSlots(script))
|
||||
setForTypes(cx, pc, script->slotTypes(slot));
|
||||
setForTypes(cx, pc, script->types.slotTypes(slot));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3887,13 +3881,13 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
|
||||
case JSOP_GENERATOR:
|
||||
if (script->fun) {
|
||||
if (script->global) {
|
||||
TypeObject *object = script->getTypeNewObject(cx, JSProto_Generator);
|
||||
if (script->hasGlobal()) {
|
||||
TypeObject *object = script->types.standardType(cx, JSProto_Generator);
|
||||
if (!object)
|
||||
return false;
|
||||
script->returnTypes()->addType(cx, (jstype) object);
|
||||
script->types.returnTypes()->addType(cx, (jstype) object);
|
||||
} else {
|
||||
script->returnTypes()->addType(cx, TYPE_UNKNOWN);
|
||||
script->types.returnTypes()->addType(cx, TYPE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -3948,7 +3942,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
||||
break;
|
||||
|
||||
case JSOP_CALLEE:
|
||||
if (script->global)
|
||||
if (script->hasGlobal())
|
||||
pushed[0].addType(cx, (jstype) script->fun->getType());
|
||||
else
|
||||
pushed[0].addType(cx, TYPE_UNKNOWN);
|
||||
@ -3981,7 +3975,7 @@ ScriptAnalysis::analyzeTypes(JSContext *cx)
|
||||
* script and trying to reanalyze here can cause reentrance problems if we
|
||||
* try to reinitialize standard classes that were cleared).
|
||||
*/
|
||||
if (script->global && script->global->isCleared())
|
||||
if (script->hasClearedGlobal())
|
||||
return;
|
||||
|
||||
if (!ranSSA()) {
|
||||
@ -3990,7 +3984,7 @@ ScriptAnalysis::analyzeTypes(JSContext *cx)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!script->ensureTypeArray(cx)) {
|
||||
if (!script->types.ensureTypeArray(cx)) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
}
|
||||
@ -4018,7 +4012,7 @@ ScriptAnalysis::analyzeTypes(JSContext *cx)
|
||||
|
||||
/* Make sure the initial type set of all local vars includes void. */
|
||||
for (unsigned i = 0; i < script->nfixed; i++)
|
||||
script->localTypes(i)->addType(cx, TYPE_UNDEFINED);
|
||||
script->types.localTypes(i)->addType(cx, TYPE_UNDEFINED);
|
||||
|
||||
TypeInferenceState state(cx);
|
||||
|
||||
@ -4050,7 +4044,7 @@ ScriptAnalysis::analyzeTypes(JSContext *cx)
|
||||
* the script either because we ran the interpreter some before analyzing
|
||||
* or because we are reanalyzing after a GC.
|
||||
*/
|
||||
TypeIntermediate *result = script->intermediateTypes;
|
||||
TypeIntermediate *result = script->types.intermediateList;
|
||||
while (result) {
|
||||
result->replay(cx, script);
|
||||
result = result->next;
|
||||
@ -4190,8 +4184,8 @@ ScriptAnalysis::analyzeTypesNew(JSContext *cx)
|
||||
|
||||
if (script->fun->getType()->unknownProperties() ||
|
||||
script->fun->isFunctionPrototype() ||
|
||||
!script->global) {
|
||||
script->thisTypes()->addType(cx, TYPE_UNKNOWN);
|
||||
!script->hasGlobal()) {
|
||||
script->types.thisTypes()->addType(cx, TYPE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4199,7 +4193,7 @@ ScriptAnalysis::analyzeTypesNew(JSContext *cx)
|
||||
TypeSet *prototypeTypes = funType->getProperty(cx, id_prototype(cx), false);
|
||||
if (!prototypeTypes)
|
||||
return;
|
||||
prototypeTypes->addNewObject(cx, script, funType, script->thisTypes());
|
||||
prototypeTypes->addNewObject(cx, script, funType, script->types.thisTypes());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4298,14 +4292,12 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSScript *script, JS
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptAnalysis *analysis = script->analysis(cx);
|
||||
if (analysis && !analysis->ranInference())
|
||||
analysis->analyzeTypes(cx);
|
||||
if (!analysis || analysis->OOM()) {
|
||||
if (!script->ensureRanInference(cx)) {
|
||||
*pbaseobj = NULL;
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return false;
|
||||
}
|
||||
ScriptAnalysis *analysis = script->analysis(cx);
|
||||
|
||||
/*
|
||||
* Offset of the last bytecode which popped 'this' and which we have
|
||||
@ -4493,8 +4485,8 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSScript *script, JS
|
||||
*pbaseobj = NULL;
|
||||
return false;
|
||||
}
|
||||
script->addIntermediateType(funcallTrap);
|
||||
script->addIntermediateType(calleeTrap);
|
||||
script->types.addIntermediate(funcallTrap);
|
||||
script->types.addIntermediate(calleeTrap);
|
||||
funcallTrap->replay(cx, script);
|
||||
calleeTrap->replay(cx, script);
|
||||
|
||||
@ -4656,23 +4648,23 @@ ScriptAnalysis::printTypes(JSContext *cx)
|
||||
|
||||
printf("locals:");
|
||||
printf("\n return:");
|
||||
script->returnTypes()->print(cx);
|
||||
script->types.returnTypes()->print(cx);
|
||||
printf("\n this:");
|
||||
script->thisTypes()->print(cx);
|
||||
script->types.thisTypes()->print(cx);
|
||||
|
||||
for (unsigned i = 0; script->fun && i < script->fun->nargs; i++) {
|
||||
printf("\n arg%u:", i);
|
||||
script->argTypes(i)->print(cx);
|
||||
script->types.argTypes(i)->print(cx);
|
||||
}
|
||||
for (unsigned i = 0; i < script->nfixed; i++) {
|
||||
if (!trackSlot(LocalSlot(script, i))) {
|
||||
printf("\n local%u:", i);
|
||||
script->localTypes(i)->print(cx);
|
||||
script->types.localTypes(i)->print(cx);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < script->bindings.countUpvars(); i++) {
|
||||
printf("\n upvar%u:", i);
|
||||
script->upvarTypes(i)->print(cx);
|
||||
script->types.upvarTypes(i)->print(cx);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@ -4686,8 +4678,8 @@ ScriptAnalysis::printTypes(JSContext *cx)
|
||||
PrintBytecode(cx, script, pc);
|
||||
|
||||
if (js_CodeSpec[*pc].format & JOF_TYPESET) {
|
||||
TypeSet *types = script->bytecodeTypes(pc);
|
||||
printf(" typeset %d:", (int) (types - script->typeArray));
|
||||
TypeSet *types = script->types.bytecodeTypes(pc);
|
||||
printf(" typeset %d:", (int) (types - script->types.typeArray));
|
||||
types->print(cx);
|
||||
printf("\n");
|
||||
}
|
||||
@ -4723,7 +4715,8 @@ ScriptAnalysis::printTypes(JSContext *cx)
|
||||
// Interface functions
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace js { namespace types {
|
||||
namespace js {
|
||||
namespace types {
|
||||
|
||||
void
|
||||
MarkTypeCallerUnexpectedSlow(JSContext *cx, jstype type)
|
||||
@ -4781,14 +4774,14 @@ TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
|
||||
unsigned nargs = callee->getFunctionPrivate()->nargs;
|
||||
JSScript *script = callee->getFunctionPrivate()->script();
|
||||
|
||||
if (!script->ensureTypeArray(cx))
|
||||
if (!script->types.ensureTypeArray(cx))
|
||||
return;
|
||||
|
||||
if (constructing) {
|
||||
script->typeSetNewCalled(cx);
|
||||
script->types.setNewCalled(cx);
|
||||
} else {
|
||||
jstype type = GetValueType(cx, args.thisv());
|
||||
script->typeSetThis(cx, type);
|
||||
script->types.setThis(cx, type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4798,11 +4791,11 @@ TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
|
||||
*/
|
||||
unsigned arg = 0;
|
||||
for (; arg < args.argc() && arg < nargs; arg++)
|
||||
script->typeSetArgument(cx, arg, args[arg]);
|
||||
script->types.setArgument(cx, arg, args[arg]);
|
||||
|
||||
/* Watch for fewer actuals than formals to the call. */
|
||||
for (; arg < nargs; arg++)
|
||||
script->typeSetArgument(cx, arg, UndefinedValue());
|
||||
script->types.setArgument(cx, arg, UndefinedValue());
|
||||
}
|
||||
|
||||
/* Intermediate type information for a dynamic type pushed in a script. */
|
||||
@ -4854,7 +4847,7 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type)
|
||||
|
||||
/* Directly update associated type sets for applicable bytecodes. */
|
||||
if (CanHaveReadBarrier(pc)) {
|
||||
TypeSet *types = script->bytecodeTypes(pc);
|
||||
TypeSet *types = script->types.bytecodeTypes(pc);
|
||||
if (!types->hasType(type)) {
|
||||
InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
|
||||
script->id(), pc - script->code, TypeString(type));
|
||||
@ -4880,7 +4873,7 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type)
|
||||
case JSOP_GNAMEINC:
|
||||
case JSOP_GNAMEDEC: {
|
||||
jsid id = GetAtomId(cx, script, pc, 0);
|
||||
TypeObject *global = script->getGlobalType();
|
||||
TypeObject *global = script->global()->getType();
|
||||
if (!global->unknownProperties()) {
|
||||
TypeSet *types = global->getProperty(cx, id, true);
|
||||
if (!types)
|
||||
@ -4906,7 +4899,7 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type)
|
||||
*/
|
||||
uint32 slot = GetBytecodeSlot(script, pc);
|
||||
if (slot < TotalSlots(script)) {
|
||||
TypeSet *types = script->slotTypes(slot);
|
||||
TypeSet *types = script->types.slotTypes(slot);
|
||||
types->addType(cx, type);
|
||||
}
|
||||
break;
|
||||
@ -4927,15 +4920,15 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type)
|
||||
return;
|
||||
} else {
|
||||
/* Scan all intermediate types on the script to check for a dupe. */
|
||||
TypeIntermediate *result, **presult = &script->intermediateTypes;
|
||||
TypeIntermediate *result, **pstart = &script->types.intermediateList, **presult = pstart;
|
||||
while (*presult) {
|
||||
result = *presult;
|
||||
if (result->hasDynamicResult(pc - script->code, type)) {
|
||||
if (presult != &script->intermediateTypes) {
|
||||
if (presult != pstart) {
|
||||
/* Move to the head of the list, maintain LRU order. */
|
||||
*presult = result->next;
|
||||
result->next = script->intermediateTypes;
|
||||
script->intermediateTypes = result;
|
||||
result->next = *pstart;
|
||||
*pstart = result;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -4951,19 +4944,17 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type)
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
script->addIntermediateType(result);
|
||||
script->types.addIntermediate(result);
|
||||
|
||||
if (script->hasAnalysis() && script->analysis(cx)->ranInference()) {
|
||||
TypeSet *pushed = script->analysis(cx)->pushedTypes(pc, 0);
|
||||
pushed->addType(cx, type);
|
||||
} else if (script->ranInference) {
|
||||
/* Any new dynamic result triggers reanalysis and recompilation. */
|
||||
ScriptAnalysis *analysis = script->analysis(cx);
|
||||
if (!analysis) {
|
||||
if (!script->ensureRanInference(cx)) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
analysis->analyzeTypes(cx);
|
||||
}
|
||||
|
||||
/* Trigger recompilation of any inline callers. */
|
||||
@ -4981,7 +4972,7 @@ TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Val
|
||||
return;
|
||||
|
||||
jstype type = GetValueType(cx, rval);
|
||||
TypeSet *types = script->bytecodeTypes(pc);
|
||||
TypeSet *types = script->types.bytecodeTypes(pc);
|
||||
if (types->hasType(type))
|
||||
return;
|
||||
|
||||
@ -5001,7 +4992,7 @@ TypeConstraintPushAll::newType(JSContext *cx, TypeSet *source, jstype type)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// JSScript
|
||||
// TypeScript
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
@ -5084,31 +5075,32 @@ IgnorePushed(const jsbytecode *pc, unsigned index)
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::makeTypeArray(JSContext *cx)
|
||||
TypeScript::makeTypeArray(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!typeArray);
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
unsigned count = nTypeSets + TotalSlots(this) + bindings.countUpvars();
|
||||
unsigned count = numTypeSets();
|
||||
typeArray = (TypeSet *) cx->calloc_(sizeof(TypeSet) * count);
|
||||
if (!typeArray) {
|
||||
compartment->types.setPendingNukeTypes(cx);
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (unsigned i = 0; i < 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());
|
||||
unsigned nargs = fun ? fun->nargs : 0;
|
||||
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);
|
||||
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());
|
||||
for (unsigned i = 0; i < nfixed; i++)
|
||||
InferSpew(ISpewOps, "typeSet: T%p local%u #%u", localTypes(i), i, id());
|
||||
for (unsigned i = 0; i < bindings.countUpvars(); i++)
|
||||
InferSpew(ISpewOps, "typeSet: T%p upvar%u #%u", upvarTypes(i), i, id());
|
||||
InferSpew(ISpewOps, "typeSet: T%p arg%u #%u", argTypes(i), i, id);
|
||||
for (unsigned i = 0; i < script()->nfixed; i++)
|
||||
InferSpew(ISpewOps, "typeSet: T%p local%u #%u", localTypes(i), i, id);
|
||||
for (unsigned i = 0; i < script()->bindings.countUpvars(); i++)
|
||||
InferSpew(ISpewOps, "typeSet: T%p upvar%u #%u", upvarTypes(i), i, id);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -5144,18 +5136,20 @@ JSScript::typeSetFunction(JSContext *cx, JSFunction *fun)
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
JSScript::typeCheckBytecode(JSContext *cx, const jsbytecode *pc, const js::Value *sp)
|
||||
TypeScript::checkBytecode(JSContext *cx, jsbytecode *pc, const js::Value *sp)
|
||||
{
|
||||
AutoEnterTypeInference enter(cx);
|
||||
UntrapOpcode untrap(cx, script(), pc);
|
||||
|
||||
if (!(analysis_ && analysis_->ranInference()))
|
||||
if (!script()->hasAnalysis() || !script()->analysis(cx)->ranInference())
|
||||
return;
|
||||
ScriptAnalysis *analysis = script()->analysis(cx);
|
||||
|
||||
int defCount = GetDefCount(this, pc - code);
|
||||
int defCount = GetDefCount(script(), pc - script()->code);
|
||||
|
||||
for (int i = 0; i < defCount; i++) {
|
||||
const js::Value &val = sp[-defCount + i];
|
||||
TypeSet *types = analysis_->pushedTypes(pc, i);
|
||||
TypeSet *types = analysis->pushedTypes(pc, i);
|
||||
if (IgnorePushed(pc, i))
|
||||
continue;
|
||||
|
||||
@ -5164,7 +5158,7 @@ JSScript::typeCheckBytecode(JSContext *cx, const jsbytecode *pc, const js::Value
|
||||
if (!TypeMatches(cx, types, type)) {
|
||||
/* Display fine-grained debug information first */
|
||||
fprintf(stderr, "Missing type at #%u:%05u pushed %u: %s\n",
|
||||
id(), pc - code, i, TypeString(type));
|
||||
script()->id(), pc - script()->code, i, TypeString(type));
|
||||
TypeFailure(cx, "Missing type pushed %u: %s", i, TypeString(type));
|
||||
}
|
||||
|
||||
@ -5185,7 +5179,7 @@ JSScript::typeCheckBytecode(JSContext *cx, const jsbytecode *pc, const js::Value
|
||||
/* Display fine-grained debug information first */
|
||||
fprintf(stderr, "Object not %s array at #%u:%05u popped %u: %s\n",
|
||||
packed ? "packed" : "dense",
|
||||
id(), pc - code, i, object->name());
|
||||
script()->id(), pc - script()->code, i, object->name());
|
||||
TypeFailure(cx, "Object not %s array, popped %u: %s",
|
||||
packed ? "packed" : "dense", i, object->name());
|
||||
}
|
||||
@ -5535,8 +5529,10 @@ TypeCompartment::~TypeCompartment()
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::condenseTypes(JSContext *cx)
|
||||
TypeScript::condenseTypes(JSContext *cx)
|
||||
{
|
||||
JSCompartment *compartment = script()->compartment;
|
||||
|
||||
if (!CondenseTypeObjectList(cx, compartment, typeObjects))
|
||||
return false;
|
||||
|
||||
@ -5549,16 +5545,16 @@ JSScript::condenseTypes(JSContext *cx)
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned num = nTypeSets + TotalSlots(this) + bindings.countUpvars();
|
||||
unsigned num = numTypeSets();
|
||||
|
||||
if (isCachedEval ||
|
||||
(u.object && IsAboutToBeFinalized(cx, u.object)) ||
|
||||
(fun && IsAboutToBeFinalized(cx, fun))) {
|
||||
if (script()->isAboutToBeFinalized(cx)) {
|
||||
/* Release all memory associated with the persistent type sets. */
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
typeArray[i].destroy(cx);
|
||||
cx->free_(typeArray);
|
||||
typeArray = NULL;
|
||||
} else {
|
||||
/* Condense all constraints in the persistent type sets. */
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (!TypeSet::CondenseSweepTypeSet(cx, compartment, condensed, &typeArray[i]))
|
||||
return false;
|
||||
@ -5566,7 +5562,7 @@ JSScript::condenseTypes(JSContext *cx)
|
||||
}
|
||||
}
|
||||
|
||||
TypeIntermediate **presult = &intermediateTypes;
|
||||
TypeIntermediate **presult = &intermediateList;
|
||||
while (*presult) {
|
||||
TypeIntermediate *result = *presult;
|
||||
if (result->sweep(cx, compartment)) {
|
||||
@ -5580,10 +5576,45 @@ JSScript::condenseTypes(JSContext *cx)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TypeScript::trace(JSTracer *trc)
|
||||
{
|
||||
/*
|
||||
* Trace all type objects associated with the script, these can be freely
|
||||
* referenced from JIT code without needing to be pinned against GC.
|
||||
*/
|
||||
types::TypeObject *obj = typeObjects;
|
||||
while (obj) {
|
||||
if (!obj->marked)
|
||||
obj->trace(trc);
|
||||
obj = obj->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TypeScript::destroy(JSContext *cx)
|
||||
{
|
||||
/* Migrate any type objects associated with this script to the compartment. */
|
||||
while (typeObjects) {
|
||||
types::TypeObject *next = typeObjects->next;
|
||||
typeObjects->next = script()->compartment->types.objects;
|
||||
script()->compartment->types.objects = typeObjects;
|
||||
typeObjects = next;
|
||||
}
|
||||
|
||||
while (intermediateList) {
|
||||
TypeIntermediate *next = intermediateList->next;
|
||||
cx->delete_(intermediateList);
|
||||
intermediateList = next;
|
||||
}
|
||||
|
||||
cx->free_(typeArray);
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::sweepAnalysis(JSContext *cx)
|
||||
{
|
||||
SweepTypeObjectList(cx, typeObjects);
|
||||
SweepTypeObjectList(cx, types.typeObjects);
|
||||
|
||||
if (analysis_ && !compartment->activeAnalysis) {
|
||||
/*
|
||||
|
@ -785,8 +785,83 @@ struct TypeCallsite
|
||||
|
||||
/* Get the new object at this callsite. */
|
||||
inline TypeObject* getInitObject(JSContext *cx, bool isArray);
|
||||
};
|
||||
|
||||
inline bool hasGlobal();
|
||||
/* Persistent type information for a script, retained across GCs. */
|
||||
struct TypeScript
|
||||
{
|
||||
inline JSScript *script();
|
||||
|
||||
/* Lazily constructed types of variables and JOF_TYPESET ops in this script. */
|
||||
TypeSet *typeArray;
|
||||
inline unsigned numTypeSets();
|
||||
|
||||
/* Any type objects associated with this script, including initializer objects. */
|
||||
TypeObject *typeObjects;
|
||||
|
||||
/* Persistent information about stack types in this script. */
|
||||
TypeIntermediate *intermediateList;
|
||||
void addIntermediate(TypeIntermediate *type) {
|
||||
type->next = intermediateList;
|
||||
intermediateList = type;
|
||||
}
|
||||
|
||||
/* Make sure there the type array has been constructed. */
|
||||
inline bool ensureTypeArray(JSContext *cx);
|
||||
|
||||
inline TypeSet *bytecodeTypes(const jsbytecode *pc);
|
||||
inline TypeSet *returnTypes();
|
||||
inline TypeSet *thisTypes();
|
||||
inline TypeSet *argTypes(unsigned i);
|
||||
inline TypeSet *localTypes(unsigned i);
|
||||
inline TypeSet *upvarTypes(unsigned i);
|
||||
|
||||
/* Follows slot layout in jsanalyze.h, can get this/arg/local type sets. */
|
||||
inline TypeSet *slotTypes(unsigned slot);
|
||||
|
||||
private:
|
||||
bool makeTypeArray(JSContext *cx);
|
||||
public:
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Check that correct types were inferred for the values pushed by this bytecode. */
|
||||
void checkBytecode(JSContext *cx, jsbytecode *pc, const js::Value *sp);
|
||||
#endif
|
||||
|
||||
/* Get the default 'new' object for a given standard class, per the script's global. */
|
||||
inline TypeObject *standardType(JSContext *cx, JSProtoKey key);
|
||||
|
||||
/* Get a type object for an allocation site in this script. */
|
||||
inline TypeObject *initObject(JSContext *cx, const jsbytecode *pc, bool isArray);
|
||||
|
||||
/* Monitor a bytecode pushing an unexpected value. */
|
||||
inline void monitorOverflow(JSContext *cx, jsbytecode *pc);
|
||||
inline void monitorString(JSContext *cx, jsbytecode *pc);
|
||||
inline void monitorUnknown(JSContext *cx, jsbytecode *pc);
|
||||
|
||||
/* Monitor a JOF_TYPESET bytecode pushing any value into its pushed type set. */
|
||||
inline void monitor(JSContext *cx, jsbytecode *pc, const js::Value &val);
|
||||
|
||||
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
|
||||
inline void monitorAssign(JSContext *cx, jsbytecode *pc,
|
||||
JSObject *obj, jsid id, const js::Value &val);
|
||||
|
||||
/* Add a type for a variable in this script. */
|
||||
inline void setThis(JSContext *cx, jstype type);
|
||||
inline void setThis(JSContext *cx, const js::Value &value);
|
||||
inline void setThis(JSContext *cx, ClonedTypeSet *types);
|
||||
inline void setNewCalled(JSContext *cx);
|
||||
inline void setLocal(JSContext *cx, unsigned local, jstype type);
|
||||
inline void setLocal(JSContext *cx, unsigned local, const js::Value &value);
|
||||
inline void setLocal(JSContext *cx, unsigned local, ClonedTypeSet *types);
|
||||
inline void setArgument(JSContext *cx, unsigned arg, jstype type);
|
||||
inline void setArgument(JSContext *cx, unsigned arg, const js::Value &value);
|
||||
inline void setArgument(JSContext *cx, unsigned arg, ClonedTypeSet *types);
|
||||
inline void setUpvar(JSContext *cx, unsigned upvar, const js::Value &value);
|
||||
|
||||
bool condenseTypes(JSContext *cx);
|
||||
void trace(JSTracer *trc);
|
||||
void destroy(JSContext *cx);
|
||||
};
|
||||
|
||||
struct ArrayTableKey;
|
||||
|
@ -270,7 +270,7 @@ GetTypeCallerInitObject(JSContext *cx, bool isArray)
|
||||
jsbytecode *pc;
|
||||
JSScript *script = cx->stack.currentScript(&pc);
|
||||
if (script && script->compartment == cx->compartment)
|
||||
return script->getTypeInitObject(cx, pc, isArray);
|
||||
return script->types.initObject(cx, pc, isArray);
|
||||
}
|
||||
return GetTypeNewObject(cx, isArray ? JSProto_Array : JSProto_Object);
|
||||
}
|
||||
@ -428,22 +428,37 @@ FixObjectType(JSContext *cx, JSObject *obj)
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval);
|
||||
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::types::jstype type);
|
||||
|
||||
} } /* namespace js::types */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Script interface functions
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline JSScript *
|
||||
TypeScript::script()
|
||||
{
|
||||
/*
|
||||
* Each TypeScript is embedded as the 'types' field of a JSScript. They
|
||||
* have the same lifetime, the distinction is made for code separation.
|
||||
* Obtain the base pointer of the outer JSScript.
|
||||
*/
|
||||
return (JSScript *)((char *)this - offsetof(JSScript, types));
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
TypeScript::numTypeSets()
|
||||
{
|
||||
return script()->nTypeSets + analyze::TotalSlots(script()) + script()->bindings.countUpvars();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScript::ensureTypeArray(JSContext *cx)
|
||||
TypeScript::ensureTypeArray(JSContext *cx)
|
||||
{
|
||||
if (typeArray)
|
||||
return true;
|
||||
return makeTypeArray(cx);
|
||||
}
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::bytecodeTypes(const jsbytecode *pc)
|
||||
inline TypeSet *
|
||||
TypeScript::bytecodeTypes(const jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(typeArray);
|
||||
|
||||
@ -452,24 +467,27 @@ JSScript::bytecodeTypes(const jsbytecode *pc)
|
||||
JS_ASSERT(js_CodeSpec[op].format & JOF_TYPESET);
|
||||
|
||||
/* All bytecodes with type sets are JOF_ATOM, except JSOP_{GET,CALL}ELEM */
|
||||
uint16 index = (op == JSOP_GETELEM || op == JSOP_CALLELEM) ? GET_UINT16(pc) : GET_UINT16(pc + 2);
|
||||
JS_ASSERT(index < nTypeSets);
|
||||
const jsbytecode *npc = (op == JSOP_GETELEM || op == JSOP_CALLELEM) ? pc : pc + 2;
|
||||
JS_ASSERT(npc - pc + 3 == js_CodeSpec[op].length);
|
||||
|
||||
uint16 index = GET_UINT16(npc);
|
||||
JS_ASSERT(index < script()->nTypeSets);
|
||||
|
||||
return &typeArray[index];
|
||||
}
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::returnTypes()
|
||||
inline TypeSet *
|
||||
TypeScript::returnTypes()
|
||||
{
|
||||
JS_ASSERT(typeArray);
|
||||
return &typeArray[nTypeSets + js::analyze::CalleeSlot()];
|
||||
return &typeArray[script()->nTypeSets + js::analyze::CalleeSlot()];
|
||||
}
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::thisTypes()
|
||||
inline TypeSet *
|
||||
TypeScript::thisTypes()
|
||||
{
|
||||
JS_ASSERT(typeArray);
|
||||
return &typeArray[nTypeSets + js::analyze::ThisSlot()];
|
||||
return &typeArray[script()->nTypeSets + js::analyze::ThisSlot()];
|
||||
}
|
||||
|
||||
/*
|
||||
@ -478,64 +496,51 @@ JSScript::thisTypes()
|
||||
* or undefined for localTypes) and not types from subsequent assignments.
|
||||
*/
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::argTypes(unsigned i)
|
||||
inline TypeSet *
|
||||
TypeScript::argTypes(unsigned i)
|
||||
{
|
||||
JS_ASSERT(typeArray && fun && i < fun->nargs);
|
||||
return &typeArray[nTypeSets + js::analyze::ArgSlot(i)];
|
||||
JS_ASSERT(typeArray && script()->fun && i < script()->fun->nargs);
|
||||
return &typeArray[script()->nTypeSets + js::analyze::ArgSlot(i)];
|
||||
}
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::localTypes(unsigned i)
|
||||
inline TypeSet *
|
||||
TypeScript::localTypes(unsigned i)
|
||||
{
|
||||
JS_ASSERT(typeArray && i < nfixed);
|
||||
return &typeArray[nTypeSets + js::analyze::LocalSlot(this, i)];
|
||||
JS_ASSERT(typeArray && i < script()->nfixed);
|
||||
return &typeArray[script()->nTypeSets + js::analyze::LocalSlot(script(), i)];
|
||||
}
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::upvarTypes(unsigned i)
|
||||
inline TypeSet *
|
||||
TypeScript::upvarTypes(unsigned i)
|
||||
{
|
||||
JS_ASSERT(typeArray && i < bindings.countUpvars());
|
||||
return &typeArray[nTypeSets + js::analyze::TotalSlots(this) + i];
|
||||
JS_ASSERT(typeArray && i < script()->bindings.countUpvars());
|
||||
return &typeArray[script()->nTypeSets + js::analyze::TotalSlots(script()) + i];
|
||||
}
|
||||
|
||||
inline js::types::TypeSet *
|
||||
JSScript::slotTypes(unsigned slot)
|
||||
inline TypeSet *
|
||||
TypeScript::slotTypes(unsigned slot)
|
||||
{
|
||||
JS_ASSERT(typeArray && slot < js::analyze::TotalSlots(this));
|
||||
return &typeArray[nTypeSets + slot];
|
||||
JS_ASSERT(typeArray && slot < js::analyze::TotalSlots(script()));
|
||||
return &typeArray[script()->nTypeSets + slot];
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSScript::getGlobal()
|
||||
{
|
||||
JS_ASSERT(global && !global->isCleared());
|
||||
return global;
|
||||
}
|
||||
|
||||
inline js::types::TypeObject *
|
||||
JSScript::getGlobalType()
|
||||
{
|
||||
return getGlobal()->getType();
|
||||
}
|
||||
|
||||
inline js::types::TypeObject *
|
||||
JSScript::getTypeNewObject(JSContext *cx, JSProtoKey key)
|
||||
inline TypeObject *
|
||||
TypeScript::standardType(JSContext *cx, JSProtoKey key)
|
||||
{
|
||||
JSObject *proto;
|
||||
if (!js_GetClassPrototype(cx, getGlobal(), key, &proto, NULL))
|
||||
if (!js_GetClassPrototype(cx, script()->global(), key, &proto, NULL))
|
||||
return NULL;
|
||||
return proto->getNewType(cx);
|
||||
}
|
||||
|
||||
inline js::types::TypeObject *
|
||||
JSScript::getTypeInitObject(JSContext *cx, const jsbytecode *pc, bool isArray)
|
||||
inline TypeObject *
|
||||
TypeScript::initObject(JSContext *cx, const jsbytecode *pc, bool isArray)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !global)
|
||||
return js::types::GetTypeNewObject(cx, isArray ? JSProto_Array : JSProto_Object);
|
||||
if (!cx->typeInferenceEnabled() || !script()->hasGlobal())
|
||||
return GetTypeNewObject(cx, isArray ? JSProto_Array : JSProto_Object);
|
||||
|
||||
uint32 offset = pc - code;
|
||||
js::types::TypeObject *prev = NULL, *obj = typeObjects;
|
||||
uint32 offset = pc - script()->code;
|
||||
TypeObject *prev = NULL, *obj = typeObjects;
|
||||
while (obj) {
|
||||
if (isArray ? obj->initializerArray : obj->initializerObject) {
|
||||
if (obj->initializerOffset == offset) {
|
||||
@ -552,40 +557,40 @@ JSScript::getTypeInitObject(JSContext *cx, const jsbytecode *pc, bool isArray)
|
||||
obj = obj->next;
|
||||
}
|
||||
|
||||
return cx->compartment->types.newInitializerTypeObject(cx, this, offset, isArray);
|
||||
return cx->compartment->types.newInitializerTypeObject(cx, script(), offset, isArray);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeMonitor(JSContext *cx, jsbytecode *pc, const js::Value &rval)
|
||||
TypeScript::monitor(JSContext *cx, jsbytecode *pc, const js::Value &rval)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
js::types::TypeMonitorResult(cx, this, pc, rval);
|
||||
TypeMonitorResult(cx, script(), pc, rval);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeMonitorOverflow(JSContext *cx, jsbytecode *pc)
|
||||
TypeScript::monitorOverflow(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
js::types::TypeDynamicResult(cx, this, pc, js::types::TYPE_DOUBLE);
|
||||
TypeDynamicResult(cx, script(), pc, TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeMonitorString(JSContext *cx, jsbytecode *pc)
|
||||
TypeScript::monitorString(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
js::types::TypeDynamicResult(cx, this, pc, js::types::TYPE_STRING);
|
||||
TypeDynamicResult(cx, script(), pc, TYPE_STRING);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeMonitorUnknown(JSContext *cx, jsbytecode *pc)
|
||||
TypeScript::monitorUnknown(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
js::types::TypeDynamicResult(cx, this, pc, js::types::TYPE_UNKNOWN);
|
||||
TypeDynamicResult(cx, script(), pc, TYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeMonitorAssign(JSContext *cx, jsbytecode *pc,
|
||||
JSObject *obj, jsid id, const js::Value &rval)
|
||||
TypeScript::monitorAssign(JSContext *cx, jsbytecode *pc,
|
||||
JSObject *obj, jsid id, const js::Value &rval)
|
||||
{
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
/*
|
||||
@ -597,74 +602,69 @@ JSScript::typeMonitorAssign(JSContext *cx, jsbytecode *pc,
|
||||
uint32 i;
|
||||
if (js_IdIsIndex(id, &i))
|
||||
return;
|
||||
js::types::MarkTypeObjectUnknownProperties(cx, obj->getType());
|
||||
MarkTypeObjectUnknownProperties(cx, obj->getType());
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetThis(JSContext *cx, js::types::jstype type)
|
||||
TypeScript::setThis(JSContext *cx, jstype type)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
if (!ensureTypeArray(cx))
|
||||
return;
|
||||
|
||||
/* Analyze the script regardless if -a was used. */
|
||||
bool analyze = !(analysis_ && analysis_->ranInference()) &&
|
||||
cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS) && !isUncachedEval;
|
||||
bool analyze = cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS) && !script()->isUncachedEval;
|
||||
|
||||
if (!thisTypes()->hasType(type) || analyze) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setThis #%u: %s",
|
||||
id(), js::types::TypeString(type));
|
||||
InferSpew(ISpewOps, "externalType: setThis #%u: %s",
|
||||
script()->id(), TypeString(type));
|
||||
thisTypes()->addType(cx, type);
|
||||
|
||||
if (analyze && !(analysis_ && analysis_->ranInference())) {
|
||||
js::analyze::ScriptAnalysis *analysis = this->analysis(cx);
|
||||
if (!analysis)
|
||||
return;
|
||||
analysis->analyzeTypes(cx);
|
||||
}
|
||||
if (analyze)
|
||||
script()->ensureRanInference(cx);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetThis(JSContext *cx, const js::Value &value)
|
||||
TypeScript::setThis(JSContext *cx, const js::Value &value)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
typeSetThis(cx, js::types::GetValueType(cx, value));
|
||||
setThis(cx, GetValueType(cx, value));
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetThis(JSContext *cx, js::types::ClonedTypeSet *set)
|
||||
TypeScript::setThis(JSContext *cx, ClonedTypeSet *set)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
if (!ensureTypeArray(cx))
|
||||
return;
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setThis #%u", id());
|
||||
InferSpew(ISpewOps, "externalType: setThis #%u", script()->id());
|
||||
thisTypes()->addTypeSet(cx, set);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetNewCalled(JSContext *cx)
|
||||
TypeScript::setNewCalled(JSContext *cx)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || calledWithNew)
|
||||
if (!cx->typeInferenceEnabled() || script()->calledWithNew)
|
||||
return;
|
||||
calledWithNew = true;
|
||||
script()->calledWithNew = true;
|
||||
|
||||
/*
|
||||
* Determining the 'this' type used when the script is invoked with 'new'
|
||||
* happens during the script's prologue, so we don't try to pick it up from
|
||||
* dynamic calls. Instead, generate constraints modeling the construction
|
||||
* of 'this' when the script is analyzed or reanalyzed after an invoke with 'new',
|
||||
* and if 'new' is first invoked after the script has already been analyzed.
|
||||
* of 'this' when the script is analyzed or reanalyzed after an invoke with
|
||||
* 'new', and if 'new' is first invoked after the script has already been
|
||||
* analyzed.
|
||||
*/
|
||||
if (ranInference) {
|
||||
/* Regenerate types for the function. */
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
js::analyze::ScriptAnalysis *analysis = this->analysis(cx);
|
||||
if (script()->ranInference) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
analyze::ScriptAnalysis *analysis = script()->analysis(cx);
|
||||
if (!analysis)
|
||||
return;
|
||||
analysis->analyzeTypesNew(cx);
|
||||
@ -672,93 +672,90 @@ JSScript::typeSetNewCalled(JSContext *cx)
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetLocal(JSContext *cx, unsigned local, js::types::jstype type)
|
||||
TypeScript::setLocal(JSContext *cx, unsigned local, jstype type)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !ensureTypeArray(cx))
|
||||
return;
|
||||
if (!localTypes(local)->hasType(type)) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setLocal #%u %u: %s",
|
||||
id(), local, js::types::TypeString(type));
|
||||
InferSpew(ISpewOps, "externalType: setLocal #%u %u: %s",
|
||||
script()->id(), local, TypeString(type));
|
||||
localTypes(local)->addType(cx, type);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetLocal(JSContext *cx, unsigned local, const js::Value &value)
|
||||
TypeScript::setLocal(JSContext *cx, unsigned local, const js::Value &value)
|
||||
{
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
js::types::jstype type = js::types::GetValueType(cx, value);
|
||||
typeSetLocal(cx, local, type);
|
||||
jstype type = GetValueType(cx, value);
|
||||
setLocal(cx, local, type);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetLocal(JSContext *cx, unsigned local, js::types::ClonedTypeSet *set)
|
||||
TypeScript::setLocal(JSContext *cx, unsigned local, ClonedTypeSet *set)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
if (!ensureTypeArray(cx))
|
||||
return;
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setLocal #%u %u", id(), local);
|
||||
InferSpew(ISpewOps, "externalType: setLocal #%u %u", script()->id(), local);
|
||||
localTypes(local)->addTypeSet(cx, set);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetArgument(JSContext *cx, unsigned arg, js::types::jstype type)
|
||||
TypeScript::setArgument(JSContext *cx, unsigned arg, jstype type)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !ensureTypeArray(cx))
|
||||
return;
|
||||
if (!argTypes(arg)->hasType(type)) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setArg #%u %u: %s",
|
||||
id(), arg, js::types::TypeString(type));
|
||||
InferSpew(ISpewOps, "externalType: setArg #%u %u: %s",
|
||||
script()->id(), arg, TypeString(type));
|
||||
argTypes(arg)->addType(cx, type);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetArgument(JSContext *cx, unsigned arg, const js::Value &value)
|
||||
TypeScript::setArgument(JSContext *cx, unsigned arg, const js::Value &value)
|
||||
{
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
js::types::jstype type = js::types::GetValueType(cx, value);
|
||||
typeSetArgument(cx, arg, type);
|
||||
jstype type = GetValueType(cx, value);
|
||||
setArgument(cx, arg, type);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetArgument(JSContext *cx, unsigned arg, js::types::ClonedTypeSet *set)
|
||||
TypeScript::setArgument(JSContext *cx, unsigned arg, ClonedTypeSet *set)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
if (!ensureTypeArray(cx))
|
||||
return;
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setArg #%u %u", id(), arg);
|
||||
InferSpew(ISpewOps, "externalType: setArg #%u %u", script()->id(), arg);
|
||||
argTypes(arg)->addTypeSet(cx, set);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::typeSetUpvar(JSContext *cx, unsigned upvar, const js::Value &value)
|
||||
TypeScript::setUpvar(JSContext *cx, unsigned upvar, const js::Value &value)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !ensureTypeArray(cx))
|
||||
return;
|
||||
js::types::jstype type = js::types::GetValueType(cx, value);
|
||||
jstype type = GetValueType(cx, value);
|
||||
if (!upvarTypes(upvar)->hasType(type)) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
js::types::InferSpew(js::types::ISpewOps, "externalType: setUpvar #%u %u: %s",
|
||||
id(), upvar, js::types::TypeString(type));
|
||||
InferSpew(ISpewOps, "externalType: setUpvar #%u %u: %s",
|
||||
script()->id(), upvar, TypeString(type));
|
||||
upvarTypes(upvar)->addType(cx, type);
|
||||
}
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace types {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeCompartment
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -1160,18 +1157,12 @@ TypeCallsite::TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
inline TypeObject *
|
||||
TypeCallsite::getInitObject(JSContext *cx, bool isArray)
|
||||
{
|
||||
TypeObject *type = script->getTypeInitObject(cx, pc, isArray);
|
||||
TypeObject *type = script->types.initObject(cx, pc, isArray);
|
||||
if (!type)
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return type;
|
||||
}
|
||||
|
||||
inline bool
|
||||
TypeCallsite::hasGlobal()
|
||||
{
|
||||
return script->global;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeObject
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -1293,6 +1284,25 @@ class AutoTypeRooter : private AutoGCRooter {
|
||||
|
||||
} } /* namespace js::types */
|
||||
|
||||
inline bool
|
||||
JSScript::isAboutToBeFinalized(JSContext *cx)
|
||||
{
|
||||
return isCachedEval ||
|
||||
(u.object && IsAboutToBeFinalized(cx, u.object)) ||
|
||||
(fun && IsAboutToBeFinalized(cx, fun));
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScript::ensureRanInference(JSContext *cx)
|
||||
{
|
||||
js::analyze::ScriptAnalysis *analysis = this->analysis(cx);
|
||||
if (analysis && !analysis->ranInference()) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
analysis->analyzeTypes(cx);
|
||||
}
|
||||
return analysis && !analysis->OOM();
|
||||
}
|
||||
|
||||
inline void
|
||||
js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32 offset, uint32 which,
|
||||
js::types::jstype type)
|
||||
|
@ -534,7 +534,7 @@ js_OnUnknownMethod(JSContext *cx, Value *vp)
|
||||
AutoValueRooter tvr(cx);
|
||||
if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, tvr.addr()))
|
||||
return false;
|
||||
cx->fp()->script()->typeMonitorUnknown(cx, cx->regs().pc);
|
||||
cx->fp()->script()->types.monitorUnknown(cx, cx->regs().pc);
|
||||
|
||||
if (tvr.value().isPrimitive()) {
|
||||
vp[0] = tvr.value();
|
||||
@ -768,9 +768,9 @@ InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &this
|
||||
* possible values the InvokeSession's client could pass in.
|
||||
*/
|
||||
jstype type = GetValueType(cx, thisv);
|
||||
script_->typeSetThis(cx, type);
|
||||
script_->types.setThis(cx, type);
|
||||
for (unsigned i = 0; i < fun->nargs; i++)
|
||||
script_->typeSetArgument(cx, i, TYPE_UNKNOWN);
|
||||
script_->types.setArgument(cx, i, TYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
@ -998,7 +998,7 @@ Execute(JSContext *cx, JSObject &chain, JSScript *script, StackFrame *prev, uint
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
jstype type = GetValueType(cx, frame.fp()->thisValue());
|
||||
script->typeSetThis(cx, type);
|
||||
script->types.setThis(cx, type);
|
||||
}
|
||||
|
||||
/* Run script until JSOP_STOP or error. */
|
||||
@ -2185,7 +2185,7 @@ TypeCheckNextBytecode(JSContext *cx, JSScript *script, unsigned n, const FrameRe
|
||||
if (cx->typeInferenceEnabled() &&
|
||||
*regs.pc != JSOP_TRAP &&
|
||||
n == analyze::GetBytecodeLength(regs.pc)) {
|
||||
script->typeCheckBytecode(cx, regs.pc, regs.sp);
|
||||
script->types.checkBytecode(cx, regs.pc, regs.sp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -2565,7 +2565,7 @@ Interpret(JSContext *cx, StackFrame *entryFrame, uintN inlineCallCount, InterpMo
|
||||
#endif
|
||||
|
||||
/* Any script we interpret needs to have its type sets filled in. */
|
||||
if (cx->typeInferenceEnabled() && !script->ensureTypeArray(cx))
|
||||
if (cx->typeInferenceEnabled() && !script->types.ensureTypeArray(cx))
|
||||
goto error;
|
||||
|
||||
/* Don't call the script prologue if executing between Method and Trace JIT. */
|
||||
@ -3585,7 +3585,7 @@ BEGIN_CASE(JSOP_URSH)
|
||||
|
||||
regs.sp--;
|
||||
if (!regs.sp[-1].setNumber(uint32(u)))
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
}
|
||||
END_CASE(JSOP_URSH)
|
||||
|
||||
@ -3600,7 +3600,7 @@ BEGIN_CASE(JSOP_ADD)
|
||||
regs.sp--;
|
||||
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) {
|
||||
regs.sp[-1].setDouble(double(l) + double(r));
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
} else {
|
||||
regs.sp[-1].setInt32(sum);
|
||||
}
|
||||
@ -3611,7 +3611,7 @@ BEGIN_CASE(JSOP_ADD)
|
||||
goto error;
|
||||
regs.sp--;
|
||||
regs.sp[-1] = rval;
|
||||
script->typeMonitorUnknown(cx, regs.pc);
|
||||
script->types.monitorUnknown(cx, regs.pc);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -3643,7 +3643,7 @@ BEGIN_CASE(JSOP_ADD)
|
||||
if (!str)
|
||||
goto error;
|
||||
if (lIsObject || rIsObject)
|
||||
script->typeMonitorString(cx, regs.pc);
|
||||
script->types.monitorString(cx, regs.pc);
|
||||
regs.sp--;
|
||||
regs.sp[-1].setString(str);
|
||||
} else {
|
||||
@ -3654,7 +3654,7 @@ BEGIN_CASE(JSOP_ADD)
|
||||
regs.sp--;
|
||||
if (!regs.sp[-1].setNumber(l) &&
|
||||
(lIsObject || rIsObject || (!lval.isDouble() && !rval.isDouble()))) {
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3674,7 +3674,7 @@ END_CASE(JSOP_ADD)
|
||||
regs.sp--; \
|
||||
if (!regs.sp[-1].setNumber(d) && \
|
||||
!(lval.isDouble() || rval.isDouble())) { \
|
||||
script->typeMonitorOverflow(cx, regs.pc); \
|
||||
script->types.monitorOverflow(cx, regs.pc); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
@ -3713,12 +3713,12 @@ BEGIN_CASE(JSOP_DIV)
|
||||
else
|
||||
vp = &rt->positiveInfinityValue;
|
||||
regs.sp[-1] = *vp;
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
} else {
|
||||
d1 /= d2;
|
||||
if (!regs.sp[-1].setNumber(d1) &&
|
||||
!(lval.isDouble() || rval.isDouble())) {
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3747,7 +3747,7 @@ BEGIN_CASE(JSOP_MOD)
|
||||
d1 = js_fmod(d1, d2);
|
||||
regs.sp[-1].setDouble(d1);
|
||||
}
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_MOD)
|
||||
@ -3789,7 +3789,7 @@ BEGIN_CASE(JSOP_NEG)
|
||||
goto error;
|
||||
d = -d;
|
||||
if (!regs.sp[-1].setNumber(d) && !ref.isDouble())
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_NEG)
|
||||
@ -3798,7 +3798,7 @@ BEGIN_CASE(JSOP_POS)
|
||||
if (!ValueToNumber(cx, ®s.sp[-1]))
|
||||
goto error;
|
||||
if (!regs.sp[-1].isInt32())
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
END_CASE(JSOP_POS)
|
||||
|
||||
BEGIN_CASE(JSOP_DELNAME)
|
||||
@ -3904,7 +3904,7 @@ BEGIN_CASE(JSOP_PROPDEC)
|
||||
if (JSID_IS_VOID(id)) {
|
||||
FETCH_ELEMENT_ID(obj, -1, id);
|
||||
if (!JSID_IS_INT(id))
|
||||
script->typeMonitorUnknown(cx, regs.pc);
|
||||
script->types.monitorUnknown(cx, regs.pc);
|
||||
}
|
||||
goto do_incop;
|
||||
|
||||
@ -3966,7 +3966,7 @@ do_incop:
|
||||
/*
|
||||
* Add undefined to the object itself when read out during an incop.
|
||||
* The getProperty can produce undefined without being accounted for by
|
||||
* type information, and typeMonitor will not be update the object itself.
|
||||
* type information, and types.monitor will not be update the object itself.
|
||||
*/
|
||||
if (regs.sp[-1].isUndefined())
|
||||
AddTypePropertyId(cx, obj->getType(), id, types::TYPE_UNDEFINED);
|
||||
@ -4006,7 +4006,7 @@ do_incop:
|
||||
if (!js_DoIncDec(cx, cs, ®s.sp[-2], ®s.sp[-1]))
|
||||
goto error;
|
||||
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
|
||||
{
|
||||
JSAutoResolveFlags rf(cx, setPropFlags);
|
||||
@ -4081,7 +4081,7 @@ BEGIN_CASE(JSOP_LOCALINC)
|
||||
PUSH_COPY(*vp);
|
||||
if (!js_DoIncDec(cx, &js_CodeSpec[op], ®s.sp[-1], vp))
|
||||
goto error;
|
||||
script->typeMonitorOverflow(cx, regs.pc);
|
||||
script->types.monitorOverflow(cx, regs.pc);
|
||||
}
|
||||
len = JSOP_INCARG_LENGTH;
|
||||
JS_ASSERT(len == js_CodeSpec[op].length);
|
||||
@ -4188,7 +4188,7 @@ BEGIN_CASE(JSOP_LENGTH)
|
||||
}
|
||||
} while (0);
|
||||
|
||||
script->typeMonitor(cx, regs.pc, rval);
|
||||
script->types.monitor(cx, regs.pc, rval);
|
||||
|
||||
regs.sp[-1] = rval;
|
||||
assertSameCompartment(cx, regs.sp[-1]);
|
||||
@ -4283,7 +4283,7 @@ BEGIN_CASE(JSOP_CALLPROP)
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
script->typeMonitor(cx, regs.pc, rval);
|
||||
script->types.monitor(cx, regs.pc, rval);
|
||||
}
|
||||
END_CASE(JSOP_CALLPROP)
|
||||
|
||||
@ -4461,7 +4461,7 @@ BEGIN_CASE(JSOP_GETELEM)
|
||||
goto error;
|
||||
regs.sp--;
|
||||
regs.sp[-1].setString(str);
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-1]);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-1]);
|
||||
len = JSOP_GETELEM_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
@ -4471,7 +4471,7 @@ BEGIN_CASE(JSOP_GETELEM)
|
||||
if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
|
||||
regs.sp--;
|
||||
regs.sp[-1] = regs.fp()->canonicalActualArg(rref.toInt32());
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-1]);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-1]);
|
||||
len = JSOP_GETELEM_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
@ -4528,13 +4528,13 @@ BEGIN_CASE(JSOP_GETELEM)
|
||||
copyFrom = &rval;
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
script->typeMonitorUnknown(cx, regs.pc);
|
||||
script->types.monitorUnknown(cx, regs.pc);
|
||||
|
||||
end_getelem:
|
||||
regs.sp--;
|
||||
regs.sp[-1] = *copyFrom;
|
||||
assertSameCompartment(cx, regs.sp[-1]);
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-1]);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-1]);
|
||||
}
|
||||
END_CASE(JSOP_GETELEM)
|
||||
|
||||
@ -4568,8 +4568,8 @@ BEGIN_CASE(JSOP_CALLELEM)
|
||||
}
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
script->typeMonitorUnknown(cx, regs.pc);
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-2]);
|
||||
script->types.monitorUnknown(cx, regs.pc);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-2]);
|
||||
}
|
||||
END_CASE(JSOP_CALLELEM)
|
||||
|
||||
@ -4581,7 +4581,7 @@ BEGIN_CASE(JSOP_SETHOLE)
|
||||
jsid id;
|
||||
FETCH_ELEMENT_ID(obj, -2, id);
|
||||
Value rval;
|
||||
script->typeMonitorAssign(cx, regs.pc, obj, id, regs.sp[-1]);
|
||||
script->types.monitorAssign(cx, regs.pc, obj, id, regs.sp[-1]);
|
||||
do {
|
||||
if (obj->isDenseArray() && JSID_IS_INT(id)) {
|
||||
jsuint length = obj->getDenseArrayInitializedLength();
|
||||
@ -4842,7 +4842,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
PUSH_COPY(rval);
|
||||
}
|
||||
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-1]);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-1]);
|
||||
|
||||
JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
@ -4861,7 +4861,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
JSOp op2 = js_GetOpcode(cx, script, regs.pc + JSOP_NAME_LENGTH);
|
||||
if (op2 == JSOP_TYPEOF) {
|
||||
PUSH_UNDEFINED();
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-1]);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-1]);
|
||||
len = JSOP_NAME_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
@ -4882,7 +4882,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
}
|
||||
|
||||
PUSH_COPY(rval);
|
||||
script->typeMonitor(cx, regs.pc, rval);
|
||||
script->types.monitor(cx, regs.pc, rval);
|
||||
|
||||
/* obj must be on the scope chain, thus not a function. */
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
@ -5179,12 +5179,7 @@ BEGIN_CASE(JSOP_ARGUMENTS)
|
||||
{
|
||||
Value rval;
|
||||
if (cx->typeInferenceEnabled() && !script->strictModeCode) {
|
||||
analyze::ScriptAnalysis *analysis = script->analysis(cx);
|
||||
if (analysis && !analysis->ranInference()) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
analysis->analyzeTypes(cx);
|
||||
}
|
||||
if (!analysis || analysis->OOM())
|
||||
if (!script->ensureRanInference(cx))
|
||||
goto error;
|
||||
if (script->fun->getType()->hasAnyFlags(types::OBJECT_FLAG_CREATED_ARGUMENTS)) {
|
||||
if (!js_GetArgsValue(cx, regs.fp(), &rval))
|
||||
@ -5340,7 +5335,7 @@ BEGIN_CASE(JSOP_CALLGLOBAL)
|
||||
JSObject *obj = regs.fp()->scopeChain().getGlobal();
|
||||
JS_ASSERT(obj->containsSlot(slot));
|
||||
PUSH_COPY(obj->getSlot(slot));
|
||||
script->typeMonitor(cx, regs.pc, regs.sp[-1]);
|
||||
script->types.monitor(cx, regs.pc, regs.sp[-1]);
|
||||
if (op == JSOP_CALLGLOBAL)
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
@ -5895,7 +5890,7 @@ BEGIN_CASE(JSOP_NEWINIT)
|
||||
if (!obj)
|
||||
goto error;
|
||||
|
||||
TypeObject *type = script->getTypeInitObject(cx, regs.pc, i == JSProto_Array);
|
||||
TypeObject *type = script->types.initObject(cx, regs.pc, i == JSProto_Array);
|
||||
if (!type)
|
||||
goto error;
|
||||
if (i == JSProto_Array) {
|
||||
@ -5917,7 +5912,7 @@ BEGIN_CASE(JSOP_NEWARRAY)
|
||||
if (!obj)
|
||||
goto error;
|
||||
|
||||
TypeObject *type = script->getTypeInitObject(cx, regs.pc, true);
|
||||
TypeObject *type = script->types.initObject(cx, regs.pc, true);
|
||||
if (!type)
|
||||
goto error;
|
||||
obj->setType(type);
|
||||
@ -5932,7 +5927,7 @@ BEGIN_CASE(JSOP_NEWOBJECT)
|
||||
JSObject *baseobj;
|
||||
LOAD_OBJECT(0, baseobj);
|
||||
|
||||
TypeObject *type = script->getTypeInitObject(cx, regs.pc, false);
|
||||
TypeObject *type = script->types.initObject(cx, regs.pc, false);
|
||||
if (!type)
|
||||
goto error;
|
||||
|
||||
|
@ -1252,7 +1252,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
|
||||
jsbytecode *yieldpc = gen->regs.pc - JSOP_YIELD_LENGTH;
|
||||
JS_ASSERT(JSOp(*yieldpc) == JSOP_YIELD || JSOp(*yieldpc) == JSOP_TRAP);
|
||||
|
||||
script->typeMonitorUnknown(cx, yieldpc);
|
||||
script->types.monitorUnknown(cx, yieldpc);
|
||||
|
||||
/*
|
||||
* Store the argument to send as the result of the yield
|
||||
|
@ -3039,7 +3039,7 @@ js_CreateThisForFunction(JSContext *cx, JSObject *callee, bool newType)
|
||||
type->singleton = obj;
|
||||
if (type->newScript)
|
||||
obj->setMap((Shape *) type->newScript->shape);
|
||||
calleeScript->typeSetThis(cx, (types::jstype) type);
|
||||
calleeScript->types.setThis(cx, (types::jstype) type);
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -1341,9 +1341,9 @@ JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
|
||||
if (script->compileAndGo) {
|
||||
GlobalScope *globalScope = cg->compiler()->globalScope;
|
||||
if (globalScope->globalObj && globalScope->globalObj->isGlobal())
|
||||
script->global = globalScope->globalObj->asGlobal();
|
||||
script->global_ = globalScope->globalObj->asGlobal();
|
||||
else if (cx->globalObject->isGlobal())
|
||||
script->global = cx->globalObject->asGlobal();
|
||||
script->global_ = cx->globalObject->asGlobal();
|
||||
}
|
||||
|
||||
if (cg->globalUses.length()) {
|
||||
@ -1511,23 +1511,7 @@ DestroyScript(JSContext *cx, JSScript *script)
|
||||
|
||||
JS_ASSERT(!script->hasAnalysis());
|
||||
|
||||
/* Migrate any type objects associated with this script to the compartment. */
|
||||
types::TypeObject *obj = script->typeObjects;
|
||||
while (obj) {
|
||||
types::TypeObject *next = obj->next;
|
||||
obj->next = script->compartment->types.objects;
|
||||
script->compartment->types.objects = obj;
|
||||
obj = next;
|
||||
}
|
||||
|
||||
types::TypeIntermediate *result = script->intermediateTypes;
|
||||
while (result) {
|
||||
types::TypeIntermediate *next = result->next;
|
||||
cx->delete_(result);
|
||||
result = next;
|
||||
}
|
||||
|
||||
cx->free_(script->typeArray);
|
||||
script->types.destroy(cx);
|
||||
|
||||
#if defined(JS_METHODJIT)
|
||||
mjit::ReleaseScriptCode(cx, script, true);
|
||||
@ -1609,17 +1593,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
|
||||
js_MarkScriptFilename(script->filename);
|
||||
|
||||
script->bindings.trace(trc);
|
||||
|
||||
/*
|
||||
* Trace all type objects associated with the script, these can be freely
|
||||
* referenced from JIT code without needing to be pinned against GC.
|
||||
*/
|
||||
types::TypeObject *obj = script->typeObjects;
|
||||
while (obj) {
|
||||
if (!obj->marked)
|
||||
obj->trace(trc);
|
||||
obj = obj->next;
|
||||
}
|
||||
script->types.trace(trc);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (script->jitNormal)
|
||||
|
@ -514,34 +514,37 @@ struct JSScript {
|
||||
|
||||
public:
|
||||
|
||||
/* Function this script is the body for, if there is one. */
|
||||
JSFunction *fun;
|
||||
|
||||
/*
|
||||
* Associates this script with a specific function, constructing a new type
|
||||
* object for the function.
|
||||
*/
|
||||
bool typeSetFunction(JSContext *cx, JSFunction *fun);
|
||||
|
||||
/* Global object for this script, if compileAndGo. */
|
||||
js::GlobalObject *global_;
|
||||
inline bool hasGlobal() const;
|
||||
inline js::GlobalObject *global() const;
|
||||
|
||||
inline bool hasClearedGlobal() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Unique identifier within the compartment for this script. */
|
||||
/*
|
||||
* Unique identifier within the compartment for this script, used for
|
||||
* printing analysis information.
|
||||
*/
|
||||
unsigned id_;
|
||||
unsigned id() { return id_; }
|
||||
#else
|
||||
unsigned id() { return 0; }
|
||||
#endif
|
||||
|
||||
/* Function this script is the body for, if there is one. */
|
||||
JSFunction *fun;
|
||||
|
||||
/* Global object for this script, if compileAndGo. */
|
||||
js::GlobalObject *global;
|
||||
|
||||
/* Lazily constructed types of variables and JOF_TYPESET ops in this script. */
|
||||
js::types::TypeSet *typeArray;
|
||||
|
||||
/* Any type objects associated with this script, including initializer objects. */
|
||||
js::types::TypeObject *typeObjects;
|
||||
|
||||
/* Persistent information about stack types in this script. */
|
||||
js::types::TypeIntermediate *intermediateTypes;
|
||||
void addIntermediateType(js::types::TypeIntermediate *type) {
|
||||
type->next = intermediateTypes;
|
||||
intermediateTypes = type;
|
||||
}
|
||||
|
||||
/* Bytecode analysis and type inference results for this script. Destroyed on GC. */
|
||||
/*
|
||||
* Bytecode analysis and type inference results for this script. Destroyed
|
||||
* on every GC.
|
||||
*/
|
||||
private:
|
||||
js::analyze::ScriptAnalysis *analysis_;
|
||||
void makeAnalysis(JSContext *cx);
|
||||
@ -555,72 +558,15 @@ struct JSScript {
|
||||
return analysis_;
|
||||
}
|
||||
|
||||
inline JSObject *getGlobal();
|
||||
inline js::types::TypeObject *getGlobalType();
|
||||
/* Ensure the script has current type inference results. */
|
||||
inline bool ensureRanInference(JSContext *cx);
|
||||
|
||||
/* Make sure there the type array has been constructed. */
|
||||
inline bool ensureTypeArray(JSContext *cx);
|
||||
/* Persistent type information retained across GCs. */
|
||||
js::types::TypeScript types;
|
||||
|
||||
inline js::types::TypeSet *bytecodeTypes(const jsbytecode *pc);
|
||||
inline js::types::TypeSet *returnTypes();
|
||||
inline js::types::TypeSet *thisTypes();
|
||||
inline js::types::TypeSet *argTypes(unsigned i);
|
||||
inline js::types::TypeSet *localTypes(unsigned i);
|
||||
inline js::types::TypeSet *upvarTypes(unsigned i);
|
||||
|
||||
/* Follows slot layout in jsanalyze.h, can get this/arg/local type sets. */
|
||||
inline js::types::TypeSet *slotTypes(unsigned slot);
|
||||
|
||||
private:
|
||||
bool makeTypeArray(JSContext *cx);
|
||||
public:
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Check that correct types were inferred for the values pushed by this bytecode. */
|
||||
void typeCheckBytecode(JSContext *cx, const jsbytecode *pc, const js::Value *sp);
|
||||
#endif
|
||||
|
||||
/* Get the default 'new' object for a given standard class, per the script's global. */
|
||||
inline js::types::TypeObject *getTypeNewObject(JSContext *cx, JSProtoKey key);
|
||||
|
||||
bool condenseTypes(JSContext *cx);
|
||||
inline bool isAboutToBeFinalized(JSContext *cx);
|
||||
void sweepAnalysis(JSContext *cx);
|
||||
|
||||
/* Get a type object for an allocation site in this script. */
|
||||
inline js::types::TypeObject *
|
||||
getTypeInitObject(JSContext *cx, const jsbytecode *pc, bool isArray);
|
||||
|
||||
/* Monitor a bytecode pushing an unexpected value. */
|
||||
inline void typeMonitorOverflow(JSContext *cx, jsbytecode *pc);
|
||||
inline void typeMonitorString(JSContext *cx, jsbytecode *pc);
|
||||
inline void typeMonitorUnknown(JSContext *cx, jsbytecode *pc);
|
||||
|
||||
/* Monitor a JOF_TYPESET bytecode pushing any value into its pushed type set. */
|
||||
inline void typeMonitor(JSContext *cx, jsbytecode *pc, const js::Value &val);
|
||||
|
||||
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
|
||||
inline void typeMonitorAssign(JSContext *cx, jsbytecode *pc,
|
||||
JSObject *obj, jsid id, const js::Value &val);
|
||||
|
||||
/* Add a type for a variable in this script. */
|
||||
inline void typeSetThis(JSContext *cx, js::types::jstype type);
|
||||
inline void typeSetThis(JSContext *cx, const js::Value &value);
|
||||
inline void typeSetThis(JSContext *cx, js::types::ClonedTypeSet *types);
|
||||
inline void typeSetNewCalled(JSContext *cx);
|
||||
inline void typeSetLocal(JSContext *cx, unsigned local, js::types::jstype type);
|
||||
inline void typeSetLocal(JSContext *cx, unsigned local, const js::Value &value);
|
||||
inline void typeSetLocal(JSContext *cx, unsigned local, js::types::ClonedTypeSet *types);
|
||||
inline void typeSetArgument(JSContext *cx, unsigned arg, js::types::jstype type);
|
||||
inline void typeSetArgument(JSContext *cx, unsigned arg, const js::Value &value);
|
||||
inline void typeSetArgument(JSContext *cx, unsigned arg, js::types::ClonedTypeSet *types);
|
||||
inline void typeSetUpvar(JSContext *cx, unsigned upvar, const js::Value &value);
|
||||
|
||||
/*
|
||||
* Associates this script with a specific function, constructing a new type
|
||||
* object for the function.
|
||||
*/
|
||||
bool typeSetFunction(JSContext *cx, JSFunction *fun);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
// Fast-cached pointers to make calls faster. These are also used to
|
||||
// quickly test whether there is JIT code; a NULL value means no
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "jsregexp.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsscope.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -161,4 +162,28 @@ JSScript::isEmpty() const
|
||||
return JSOp(*pc) == JSOP_STOP;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScript::hasGlobal() const
|
||||
{
|
||||
/*
|
||||
* Make sure that we don't try to query information about global objects
|
||||
* which have had their scopes cleared. compileAndGo code should not run
|
||||
* anymore against such globals.
|
||||
*/
|
||||
return global_ && !global_->isCleared();
|
||||
}
|
||||
|
||||
inline js::GlobalObject *
|
||||
JSScript::global() const
|
||||
{
|
||||
JS_ASSERT(hasGlobal());
|
||||
return global_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScript::hasClearedGlobal() const
|
||||
{
|
||||
return global_ && global_->isCleared();
|
||||
}
|
||||
|
||||
#endif /* jsscriptinlines_h___ */
|
||||
|
@ -3127,7 +3127,7 @@ static void type_StringSplit(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsit
|
||||
{
|
||||
TypeCallsite *site = Valueify(jssite);
|
||||
|
||||
if (!site->hasGlobal()) {
|
||||
if (!site->script->hasGlobal()) {
|
||||
site->returnTypes->addType(cx, TYPE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript, bool isConstructi
|
||||
outerScript(outerScript),
|
||||
isConstructing(isConstructing),
|
||||
ssa(cx, outerScript),
|
||||
globalObj(outerScript->global),
|
||||
globalObj(outerScript->hasGlobal() ? outerScript->global() : NULL),
|
||||
globalSlots(globalObj ? globalObj->getRawSlots() : NULL),
|
||||
frame(cx, *thisFromCtor(), masm, stubcc),
|
||||
a(NULL), outer(NULL), script(NULL), PC(NULL), loop(NULL),
|
||||
@ -183,33 +183,16 @@ mjit::Compiler::compile()
|
||||
CompileStatus
|
||||
mjit::Compiler::checkAnalysis(JSScript *script)
|
||||
{
|
||||
if (cx->typeInferenceEnabled() && !script->ensureRanInference(cx))
|
||||
return Compile_Error;
|
||||
|
||||
ScriptAnalysis *analysis = script->analysis(cx);
|
||||
|
||||
if (!analysis)
|
||||
return Compile_Error;
|
||||
if (!analysis->failed() && !analysis->ranBytecode())
|
||||
analysis->analyzeBytecode(cx);
|
||||
|
||||
if (analysis->OOM())
|
||||
return Compile_Error;
|
||||
if (analysis->failed()) {
|
||||
JaegerSpew(JSpew_Abort, "couldn't analyze bytecode; probably switchX or OOM\n");
|
||||
return Compile_Abort;
|
||||
}
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
if (!analysis->ranSSA())
|
||||
analysis->analyzeSSA(cx);
|
||||
if (!analysis->failed() && !analysis->ranLifetimes())
|
||||
analysis->analyzeLifetimes(cx);
|
||||
if (!analysis->failed() && !analysis->ranInference())
|
||||
analysis->analyzeTypes(cx);
|
||||
if (analysis->failed()) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return Compile_Error;
|
||||
}
|
||||
}
|
||||
|
||||
return Compile_Okay;
|
||||
}
|
||||
|
||||
@ -246,7 +229,8 @@ mjit::Compiler::scanInlineCalls(uint32 index, uint32 depth)
|
||||
ScriptAnalysis *analysis = script->analysis(cx);
|
||||
|
||||
/* Don't inline from functions which could have a non-global scope object. */
|
||||
if (script->global != globalObj ||
|
||||
if (!script->hasGlobal() ||
|
||||
script->global() != globalObj ||
|
||||
(script->fun && script->fun->getParent() != globalObj) ||
|
||||
(script->fun && script->fun->isHeavyweight()) ||
|
||||
script->isActiveEval) {
|
||||
@ -365,7 +349,7 @@ mjit::Compiler::scanInlineCalls(uint32 index, uint32 depth)
|
||||
* caller.
|
||||
*/
|
||||
if (script->analysis(cx)->usesThisValue() &&
|
||||
script->thisTypes()->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT) {
|
||||
script->types.thisTypes()->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT) {
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
@ -622,7 +606,7 @@ mjit::Compiler::prepareInferenceTypes(JSScript *script, ActiveFrame *a)
|
||||
|
||||
for (uint32 slot = ArgSlot(0); slot < TotalSlots(script); slot++) {
|
||||
VarType &vt = a->varTypes[slot];
|
||||
vt.types = script->slotTypes(slot);
|
||||
vt.types = script->types.slotTypes(slot);
|
||||
vt.type = vt.types->getKnownTypeTag(cx);
|
||||
}
|
||||
|
||||
@ -1852,7 +1836,7 @@ mjit::Compiler::generateMethod()
|
||||
/* Watch for overflow in constant propagation. */
|
||||
types::TypeSet *pushed = pushedTypeSet(0);
|
||||
if (!v.isInt32() && pushed && !pushed->hasType(types::TYPE_DOUBLE)) {
|
||||
script->typeMonitorOverflow(cx, PC);
|
||||
script->types.monitorOverflow(cx, PC);
|
||||
return Compile_Retry;
|
||||
}
|
||||
|
||||
@ -5374,7 +5358,7 @@ mjit::Compiler::jsop_this()
|
||||
|
||||
if (!thisFe->isType(JSVAL_TYPE_OBJECT)) {
|
||||
JSValueType type = cx->typeInferenceEnabled()
|
||||
? script->thisTypes()->getKnownTypeTag(cx)
|
||||
? script->types.thisTypes()->getKnownTypeTag(cx)
|
||||
: JSVAL_TYPE_UNKNOWN;
|
||||
if (type != JSVAL_TYPE_OBJECT) {
|
||||
Jump notObj = frame.testObject(Assembler::NotEqual, thisFe);
|
||||
@ -6380,7 +6364,7 @@ mjit::Compiler::jsop_newinit()
|
||||
/* Don't bake in types for non-compileAndGo scripts. */
|
||||
types::TypeObject *type = NULL;
|
||||
if (globalObj) {
|
||||
type = script->getTypeInitObject(cx, PC, isArray);
|
||||
type = script->types.initObject(cx, PC, isArray);
|
||||
if (!type)
|
||||
return false;
|
||||
}
|
||||
@ -7363,7 +7347,7 @@ mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg, bool testUnd
|
||||
return state;
|
||||
#endif
|
||||
|
||||
types::TypeSet *types = script->bytecodeTypes(PC);
|
||||
types::TypeSet *types = script->types.bytecodeTypes(PC);
|
||||
types->addFreeze(cx);
|
||||
|
||||
/* Cannot have type barriers when the result of the operation is already unknown. */
|
||||
|
@ -200,10 +200,10 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::Typ
|
||||
if (!v.isInt32() && typeSet && !typeSet->hasType(types::TYPE_DOUBLE)) {
|
||||
/*
|
||||
* OK to ignore failure here, we aren't performing the operation
|
||||
* itself. Note that typeMonitorResult will propagate the type
|
||||
* as necessary if a *INC operation overflowed.
|
||||
* itself. Note that monitorOverflow will propagate the type as
|
||||
* necessary if a *INC operation overflowed.
|
||||
*/
|
||||
script->typeMonitorOverflow(cx, PC);
|
||||
script->types.monitorOverflow(cx, PC);
|
||||
return false;
|
||||
}
|
||||
frame.popn(2);
|
||||
@ -947,7 +947,7 @@ mjit::Compiler::jsop_mod()
|
||||
if (tryBinaryConstantFold(cx, frame, JSOP_MOD, lhs, rhs, &v)) {
|
||||
types::TypeSet *pushed = pushedTypeSet(0);
|
||||
if (!v.isInt32() && pushed && !pushed->hasType(types::TYPE_DOUBLE)) {
|
||||
script->typeMonitorOverflow(cx, PC);
|
||||
script->types.monitorOverflow(cx, PC);
|
||||
return false;
|
||||
}
|
||||
frame.popn(2);
|
||||
|
@ -1152,7 +1152,7 @@ FinishVarIncOp(VMFrame &f, RejoinState rejoin, Value ov, Value nv, Value *vp)
|
||||
double d = ov.toNumber();
|
||||
double N = (cs->format & JOF_INC) ? 1 : -1;
|
||||
if (!nv.setNumber(d + N))
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
}
|
||||
|
||||
*var = nv;
|
||||
@ -1195,7 +1195,7 @@ FinishObjIncOp(VMFrame &f, RejoinState rejoin, Value objv, Value ov, Value nv, V
|
||||
double d = ov.toNumber();
|
||||
double N = (cs->format & JOF_INC) ? 1 : -1;
|
||||
if (!nv.setNumber(d + N))
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
}
|
||||
|
||||
uint32 setPropFlags = (cs->format & JOF_NAME)
|
||||
|
@ -1368,13 +1368,13 @@ ic::GenerateArgumentCheckStub(VMFrame &f)
|
||||
|
||||
if (!f.fp()->isConstructing()) {
|
||||
Address address(JSFrameReg, StackFrame::offsetOfThis(fun));
|
||||
if (!GenerateTypeCheck(f.cx, masm, address, script->thisTypes(), &mismatches))
|
||||
if (!GenerateTypeCheck(f.cx, masm, address, script->types.thisTypes(), &mismatches))
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < fun->nargs; i++) {
|
||||
Address address(JSFrameReg, StackFrame::offsetOfFormalArg(fun, i));
|
||||
if (!GenerateTypeCheck(f.cx, masm, address, script->argTypes(i), &mismatches))
|
||||
if (!GenerateTypeCheck(f.cx, masm, address, script->types.argTypes(i), &mismatches))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -642,12 +642,12 @@ class SetPropCompiler : public PICStubCompiler
|
||||
RecompilationMonitor monitor(cx);
|
||||
JSScript *script = obj->getCallObjCalleeFunction()->script();
|
||||
uint16 slot = uint16(shape->shortid);
|
||||
if (!script->ensureTypeArray(cx))
|
||||
if (!script->types.ensureTypeArray(cx))
|
||||
return error();
|
||||
if (shape->setterOp() == SetCallArg)
|
||||
script->typeSetArgument(cx, slot, pic.rhsTypes);
|
||||
script->types.setArgument(cx, slot, pic.rhsTypes);
|
||||
else
|
||||
script->typeSetLocal(cx, slot, pic.rhsTypes);
|
||||
script->types.setLocal(cx, slot, pic.rhsTypes);
|
||||
if (monitor.recompiled())
|
||||
return Lookup_Uncacheable;
|
||||
}
|
||||
@ -929,7 +929,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
JS_ASSERT(pic.hasTypeCheck());
|
||||
JS_ASSERT(pic.kind == ic::PICInfo::CALL);
|
||||
|
||||
if (!f.fp()->script()->global)
|
||||
if (!f.fp()->script()->hasGlobal())
|
||||
return disable("String.prototype without compile-and-go global");
|
||||
|
||||
GetPropertyHelper<GetPropCompiler> getprop(cx, obj, atom, *this, f);
|
||||
@ -1626,20 +1626,17 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
* does not keep track of this information, so ensure that we ran type
|
||||
* inference on the parent script before doing propagation.
|
||||
*/
|
||||
analyze::ScriptAnalysis *analysis = newscript->analysis(cx);
|
||||
if (analysis && !analysis->ranInference())
|
||||
analysis->analyzeTypes(cx);
|
||||
if (!analysis || analysis->OOM())
|
||||
if (!newscript->ensureRanInference(cx))
|
||||
return false;
|
||||
|
||||
if (shape->getterOp() == GetCallArg)
|
||||
types = newscript->argTypes(slot);
|
||||
types = newscript->types.argTypes(slot);
|
||||
else if (shape->getterOp() == GetCallVar)
|
||||
types = newscript->localTypes(slot);
|
||||
types = newscript->types.localTypes(slot);
|
||||
} else {
|
||||
JS_ASSERT(!getprop.obj->getParent());
|
||||
if (getprop.obj->getType()->unknownProperties()) {
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
return true;
|
||||
}
|
||||
types = getprop.obj->getType()->getProperty(cx, shape->propid, false);
|
||||
@ -1807,11 +1804,11 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
THROW();
|
||||
JSString *str = f.regs.sp[-1].toString();
|
||||
f.regs.sp[-1].setInt32(str->length());
|
||||
f.script()->typeMonitor(f.cx, f.pc(), f.regs.sp[-1]);
|
||||
f.script()->types.monitor(f.cx, f.pc(), f.regs.sp[-1]);
|
||||
return;
|
||||
} else if (f.regs.sp[-1].isMagic(JS_LAZY_ARGUMENTS)) {
|
||||
f.regs.sp[-1].setInt32(f.regs.fp()->numActualArgs());
|
||||
f.script()->typeMonitor(f.cx, f.pc(), f.regs.sp[-1]);
|
||||
f.script()->types.monitor(f.cx, f.pc(), f.regs.sp[-1]);
|
||||
return;
|
||||
} else if (!f.regs.sp[-1].isPrimitive()) {
|
||||
JSObject *obj = &f.regs.sp[-1].toObject();
|
||||
@ -1836,7 +1833,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
JSString *str = obj->getPrimitiveThis().toString();
|
||||
f.regs.sp[-1].setInt32(str->length());
|
||||
}
|
||||
f.script()->typeMonitor(f.cx, f.pc(), f.regs.sp[-1]);
|
||||
f.script()->types.monitor(f.cx, f.pc(), f.regs.sp[-1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1879,7 +1876,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
* reads of the prototype.
|
||||
*/
|
||||
if (usePropCache)
|
||||
f.script()->typeMonitor(f.cx, f.pc(), v);
|
||||
f.script()->types.monitor(f.cx, f.pc(), v);
|
||||
|
||||
f.regs.sp[-1] = v;
|
||||
}
|
||||
@ -2045,7 +2042,7 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic)
|
||||
}
|
||||
#endif
|
||||
|
||||
f.script()->typeMonitor(cx, f.pc(), regs.sp[-2]);
|
||||
f.script()->types.monitor(cx, f.pc(), regs.sp[-2]);
|
||||
|
||||
if (monitor.recompiled())
|
||||
return;
|
||||
@ -2099,7 +2096,7 @@ ic::XName(VMFrame &f, ic::PICInfo *pic)
|
||||
THROW();
|
||||
f.regs.sp[-1] = rval;
|
||||
|
||||
f.script()->typeMonitor(f.cx, f.pc(), rval);
|
||||
f.script()->types.monitor(f.cx, f.pc(), rval);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -2120,7 +2117,7 @@ ic::Name(VMFrame &f, ic::PICInfo *pic)
|
||||
|
||||
if (status == Lookup_Cacheable && !cc.updateTypes())
|
||||
THROW();
|
||||
f.script()->typeMonitor(f.cx, f.pc(), rval);
|
||||
f.script()->types.monitor(f.cx, f.pc(), rval);
|
||||
}
|
||||
|
||||
static void JS_FASTCALL
|
||||
@ -2149,7 +2146,7 @@ ic::CallName(VMFrame &f, ic::PICInfo *pic)
|
||||
|
||||
if (status == Lookup_Cacheable && !cc.updateTypes())
|
||||
THROW();
|
||||
f.script()->typeMonitor(f.cx, f.pc(), rval);
|
||||
f.script()->types.monitor(f.cx, f.pc(), rval);
|
||||
}
|
||||
|
||||
static void JS_FASTCALL
|
||||
@ -2607,8 +2604,8 @@ ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
|
||||
JS_ASSERT(!f.regs.sp[-2].isMagic());
|
||||
f.regs.sp[-1].setObject(*thisObj);
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2629,8 +2626,8 @@ ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
|
||||
f.regs.sp[-1] = thisv;
|
||||
}
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -2673,8 +2670,8 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic)
|
||||
// If the result can be cached, the value was already retrieved.
|
||||
JS_ASSERT(!f.regs.sp[-2].isMagic());
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2682,8 +2679,8 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic)
|
||||
if (!obj->getProperty(cx, id, &f.regs.sp[-2]))
|
||||
THROW();
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
}
|
||||
|
||||
#define APPLY_STRICTNESS(f, s) \
|
||||
|
@ -370,7 +370,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
|
||||
if (op2 == JSOP_TYPEOF) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-1]);
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-1]);
|
||||
return obj;
|
||||
}
|
||||
ReportAtomNotDefined(cx, atom);
|
||||
@ -397,7 +397,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname)
|
||||
AddTypePropertyId(cx, obj->getType(), id, TYPE_UNDEFINED);
|
||||
}
|
||||
|
||||
f.script()->typeMonitor(cx, f.pc(), rval);
|
||||
f.script()->types.monitor(cx, f.pc(), rval);
|
||||
|
||||
*f.regs.sp++ = rval;
|
||||
|
||||
@ -438,7 +438,7 @@ stubs::GetElem(VMFrame &f)
|
||||
if (!str)
|
||||
THROW();
|
||||
f.regs.sp[-2].setString(str);
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -446,7 +446,7 @@ stubs::GetElem(VMFrame &f)
|
||||
if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
|
||||
if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
|
||||
regs.sp[-2] = regs.fp()->canonicalActualArg(rref.toInt32());
|
||||
f.script()->typeMonitor(cx, f.pc(), regs.sp[-2]);
|
||||
f.script()->types.monitor(cx, f.pc(), regs.sp[-2]);
|
||||
return;
|
||||
}
|
||||
MarkTypeObjectFlags(cx, f.script()->fun->getType(),
|
||||
@ -505,11 +505,11 @@ stubs::GetElem(VMFrame &f)
|
||||
copyFrom = &rval;
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
|
||||
end_getelem:
|
||||
f.regs.sp[-2] = *copyFrom;
|
||||
f.script()->typeMonitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
f.script()->types.monitor(cx, f.pc(), f.regs.sp[-2]);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@ -556,8 +556,8 @@ stubs::CallElem(VMFrame &f)
|
||||
regs.sp[-1] = thisv;
|
||||
}
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->typeMonitor(cx, f.pc(), regs.sp[-2]);
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitor(cx, f.pc(), regs.sp[-2]);
|
||||
}
|
||||
|
||||
template<JSBool strict>
|
||||
@ -581,7 +581,7 @@ stubs::SetElem(VMFrame &f)
|
||||
if (!FetchElementId(f, obj, idval, id, ®s.sp[-2]))
|
||||
THROW();
|
||||
|
||||
f.script()->typeMonitorAssign(cx, f.pc(), obj, id, rval);
|
||||
f.script()->types.monitorAssign(cx, f.pc(), obj, id, rval);
|
||||
|
||||
do {
|
||||
if (obj->isDenseArray() && JSID_IS_INT(id)) {
|
||||
@ -727,7 +727,7 @@ stubs::Ursh(VMFrame &f)
|
||||
u >>= (j & 31);
|
||||
|
||||
if (!f.regs.sp[-2].setNumber(uint32(u)))
|
||||
f.script()->typeMonitorOverflow(f.cx, f.pc());
|
||||
f.script()->types.monitorOverflow(f.cx, f.pc());
|
||||
}
|
||||
|
||||
template<JSBool strict>
|
||||
@ -1054,7 +1054,7 @@ MonitorArithmeticOverflow(VMFrame &f, const Value &v)
|
||||
JSContext *cx = f.cx;
|
||||
|
||||
JS_ASSERT(v.isDouble());
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
|
||||
/*
|
||||
* Monitoring the overflow is not enough for fused INC operations on NAME/PROP,
|
||||
@ -1113,7 +1113,7 @@ stubs::Add(VMFrame &f)
|
||||
THROW();
|
||||
regs.sp--;
|
||||
regs.sp[-1] = rval;
|
||||
f.script()->typeMonitorUnknown(cx, f.pc());
|
||||
f.script()->types.monitorUnknown(cx, f.pc());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -1141,7 +1141,7 @@ stubs::Add(VMFrame &f)
|
||||
regs.sp[-1].setString(rstr);
|
||||
}
|
||||
if (lIsObject || rIsObject)
|
||||
f.script()->typeMonitorString(cx, f.pc());
|
||||
f.script()->types.monitorString(cx, f.pc());
|
||||
goto string_concat;
|
||||
|
||||
} else {
|
||||
@ -1193,7 +1193,7 @@ stubs::Mul(VMFrame &f)
|
||||
}
|
||||
double d = d1 * d2;
|
||||
if (!regs.sp[-2].setNumber(d))
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -1223,11 +1223,11 @@ stubs::Div(VMFrame &f)
|
||||
else
|
||||
vp = &rt->positiveInfinityValue;
|
||||
regs.sp[-2] = *vp;
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
} else {
|
||||
d1 /= d2;
|
||||
if (!regs.sp[-2].setNumber(d1))
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1256,7 +1256,7 @@ stubs::Mod(VMFrame &f)
|
||||
d1 = js_fmod(d1, d2);
|
||||
regs.sp[-2].setDouble(d1);
|
||||
}
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1373,7 +1373,7 @@ stubs::Neg(VMFrame &f)
|
||||
THROW();
|
||||
d = -d;
|
||||
if (!f.regs.sp[-1].setNumber(d))
|
||||
f.script()->typeMonitorOverflow(f.cx, f.pc());
|
||||
f.script()->types.monitorOverflow(f.cx, f.pc());
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
@ -1679,7 +1679,7 @@ ObjIncOp(VMFrame &f, JSObject *obj, jsid id)
|
||||
}
|
||||
|
||||
v.setNumber(d);
|
||||
f.script()->typeMonitorOverflow(cx, f.pc());
|
||||
f.script()->types.monitorOverflow(cx, f.pc());
|
||||
|
||||
{
|
||||
JSAutoResolveFlags rf(cx, setPropFlags);
|
||||
@ -1804,7 +1804,7 @@ stubs::ElemInc(VMFrame &f)
|
||||
f.regs.sp[-3] = f.regs.sp[-1];
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(f.cx, f.pc());
|
||||
f.script()->types.monitorUnknown(f.cx, f.pc());
|
||||
}
|
||||
|
||||
template void JS_FASTCALL stubs::ElemInc<true>(VMFrame &f);
|
||||
@ -1825,7 +1825,7 @@ stubs::ElemDec(VMFrame &f)
|
||||
f.regs.sp[-3] = f.regs.sp[-1];
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(f.cx, f.pc());
|
||||
f.script()->types.monitorUnknown(f.cx, f.pc());
|
||||
}
|
||||
|
||||
template void JS_FASTCALL stubs::ElemDec<true>(VMFrame &f);
|
||||
@ -1846,7 +1846,7 @@ stubs::IncElem(VMFrame &f)
|
||||
f.regs.sp[-3] = f.regs.sp[-1];
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(f.cx, f.pc());
|
||||
f.script()->types.monitorUnknown(f.cx, f.pc());
|
||||
}
|
||||
|
||||
template void JS_FASTCALL stubs::IncElem<true>(VMFrame &f);
|
||||
@ -1867,7 +1867,7 @@ stubs::DecElem(VMFrame &f)
|
||||
f.regs.sp[-3] = f.regs.sp[-1];
|
||||
|
||||
if (!JSID_IS_INT(id))
|
||||
f.script()->typeMonitorUnknown(f.cx, f.pc());
|
||||
f.script()->types.monitorUnknown(f.cx, f.pc());
|
||||
}
|
||||
|
||||
template void JS_FASTCALL stubs::DecElem<true>(VMFrame &f);
|
||||
@ -1980,7 +1980,7 @@ InlineGetProp(VMFrame &f)
|
||||
if (vp->isMagic(JS_LAZY_ARGUMENTS)) {
|
||||
JS_ASSERT(js_GetOpcode(cx, f.script(), f.pc()) == JSOP_LENGTH);
|
||||
regs.sp[-1] = Int32Value(regs.fp()->numActualArgs());
|
||||
f.script()->typeMonitor(cx, f.pc(), regs.sp[-1]);
|
||||
f.script()->types.monitor(cx, f.pc(), regs.sp[-1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2029,7 +2029,7 @@ InlineGetProp(VMFrame &f)
|
||||
}
|
||||
} while(0);
|
||||
|
||||
f.script()->typeMonitor(cx, f.pc(), rval);
|
||||
f.script()->types.monitor(cx, f.pc(), rval);
|
||||
|
||||
regs.sp[-1] = rval;
|
||||
return true;
|
||||
@ -2149,7 +2149,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
|
||||
THROW();
|
||||
}
|
||||
#endif
|
||||
f.script()->typeMonitor(cx, f.pc(), rval);
|
||||
f.script()->types.monitor(cx, f.pc(), rval);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -2601,7 +2601,7 @@ stubs::Pos(VMFrame &f)
|
||||
if (!ValueToNumber(f.cx, &f.regs.sp[-1]))
|
||||
THROW();
|
||||
if (!f.regs.sp[-1].isInt32())
|
||||
f.script()->typeMonitorOverflow(f.cx, f.pc());
|
||||
f.script()->types.monitorOverflow(f.cx, f.pc());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -2781,14 +2781,14 @@ stubs::TypeBarrierHelper(VMFrame &f, uint32 which)
|
||||
f.script()->analysis(f.cx)->breakTypeBarriers(f.cx, f.pc() - f.script()->code, false);
|
||||
}
|
||||
|
||||
f.script()->typeMonitor(f.cx, f.pc(), result);
|
||||
f.script()->types.monitor(f.cx, f.pc(), result);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::NegZeroHelper(VMFrame &f)
|
||||
{
|
||||
f.regs.sp[-1].setDouble(-0.0);
|
||||
f.script()->typeMonitorOverflow(f.cx, f.pc());
|
||||
f.script()->types.monitorOverflow(f.cx, f.pc());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -2823,9 +2823,9 @@ stubs::CheckArgumentTypes(VMFrame &f)
|
||||
types::AutoEnterTypeInference enter(f.cx);
|
||||
|
||||
if (!f.fp()->isConstructing())
|
||||
script->typeSetThis(f.cx, fp->thisValue());
|
||||
script->types.setThis(f.cx, fp->thisValue());
|
||||
for (unsigned i = 0; i < fun->nargs; i++)
|
||||
script->typeSetArgument(f.cx, i, fp->formalArg(i));
|
||||
script->types.setArgument(f.cx, i, fp->formalArg(i));
|
||||
}
|
||||
|
||||
if (monitor.recompiled())
|
||||
@ -2845,12 +2845,12 @@ stubs::AssertArgumentTypes(VMFrame &f)
|
||||
JSScript *script = fun->script();
|
||||
|
||||
jstype type = GetValueType(f.cx, fp->thisValue());
|
||||
if (!TypeMatches(f.cx, script->thisTypes(), type))
|
||||
if (!TypeMatches(f.cx, script->types.thisTypes(), type))
|
||||
TypeFailure(f.cx, "Missing type for this: %s", TypeString(type));
|
||||
|
||||
for (unsigned i = 0; i < fun->nargs; i++) {
|
||||
type = GetValueType(f.cx, fp->formalArg(i));
|
||||
if (!TypeMatches(f.cx, script->argTypes(i), type))
|
||||
if (!TypeMatches(f.cx, script->types.argTypes(i), type))
|
||||
TypeFailure(f.cx, "Missing type for arg %d: %s", i, TypeString(type));
|
||||
}
|
||||
}
|
||||
|
@ -726,9 +726,13 @@ FrameRegsIter::incSlow(StackFrame *oldfp)
|
||||
/*****************************************************************************/
|
||||
|
||||
AllFramesIter::AllFramesIter(JSContext *cx)
|
||||
: seg_(cx->stack.currentSegment()),
|
||||
fp_(seg_ ? seg_->currentFrame() : NULL)
|
||||
: seg_(cx->stack.currentSegment())
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::ExpandInlineFrames(cx, true);
|
||||
#endif
|
||||
|
||||
fp_ = seg_ ? seg_->currentFrame() : NULL;
|
||||
}
|
||||
|
||||
AllFramesIter&
|
||||
|
Loading…
Reference in New Issue
Block a user