mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 824473: IonMonkey: Remove use of monitoredTypesReturn to decide when inlining calls, r=dvander
This commit is contained in:
parent
6049650a20
commit
8b45633296
@ -212,7 +212,8 @@ IonBuilder::canInlineTarget(JSFunction *target)
|
||||
builder = builder->callerBuilder_;
|
||||
}
|
||||
|
||||
bool canInline = oracle->canEnterInlinedFunction(target);
|
||||
RootedScript callerScript(cx, script());
|
||||
bool canInline = oracle->canEnterInlinedFunction(callerScript, pc, target);
|
||||
|
||||
if (!canInline) {
|
||||
IonSpew(IonSpew_Inlining, "Cannot inline due to oracle veto %d", script()->lineno);
|
||||
|
@ -542,28 +542,44 @@ TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc)
|
||||
JS_ASSERT(types::IsInlinableCall(pc));
|
||||
|
||||
Bytecode *code = caller->analysis()->maybeCode(pc);
|
||||
if (code->monitoredTypes || code->monitoredTypesReturn || caller->analysis()->typeBarriers(cx, pc))
|
||||
if (code->monitoredTypes)
|
||||
return false;
|
||||
|
||||
// Gets removed in Bug 796114
|
||||
if (caller->analysis()->typeBarriers(cx, pc))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeInferenceOracle::canEnterInlinedFunction(JSFunction *target)
|
||||
TypeInferenceOracle::canEnterInlinedFunction(HandleScript caller, jsbytecode *pc, JSFunction *target)
|
||||
{
|
||||
AssertCanGC();
|
||||
RootedScript script(cx, target->nonLazyScript());
|
||||
if (!script->hasAnalysis() || !script->analysis()->ranInference())
|
||||
RootedScript targetScript(cx, target->nonLazyScript());
|
||||
if (!targetScript->hasAnalysis() || !targetScript->analysis()->ranInference())
|
||||
return false;
|
||||
|
||||
if (!script->analysis()->ionInlineable())
|
||||
if (!targetScript->analysis()->ionInlineable())
|
||||
return false;
|
||||
|
||||
if (script->analysis()->usesScopeChain())
|
||||
if (targetScript->analysis()->usesScopeChain())
|
||||
return false;
|
||||
|
||||
if (target->getType(cx)->unknownProperties())
|
||||
return false;
|
||||
|
||||
JSOp op = JSOp(*pc);
|
||||
TypeSet *returnTypes = TypeScript::ReturnTypes(targetScript);
|
||||
TypeSet *callReturn = getCallReturn(caller, pc);
|
||||
if (op == JSOP_NEW) {
|
||||
if (!returnTypes->isSubsetIgnorePrimitives(callReturn))
|
||||
return false;
|
||||
} else {
|
||||
if (!returnTypes->isSubset(callReturn))
|
||||
return false;
|
||||
}
|
||||
|
||||
// TI calls ObjectStateChange to trigger invalidation of the caller.
|
||||
HeapTypeSet::WatchObjectStateChange(cx, target->getType(cx));
|
||||
return true;
|
||||
|
@ -146,7 +146,7 @@ class TypeOracle
|
||||
virtual bool canInlineCall(HandleScript caller, jsbytecode *pc) {
|
||||
return false;
|
||||
}
|
||||
virtual bool canEnterInlinedFunction(JSFunction *callee) {
|
||||
virtual bool canEnterInlinedFunction(HandleScript caller, jsbytecode *pc, JSFunction *callee) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ class TypeInferenceOracle : public TypeOracle
|
||||
MIRType elementWrite(UnrootedScript script, jsbytecode *pc);
|
||||
bool canInlineCalls();
|
||||
bool canInlineCall(HandleScript caller, jsbytecode *pc);
|
||||
bool canEnterInlinedFunction(JSFunction *callee);
|
||||
bool canEnterInlinedFunction(HandleScript caller, jsbytecode *pc, JSFunction *callee);
|
||||
types::StackTypeSet *aliasedVarBarrier(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier);
|
||||
|
||||
LazyArgumentsType isArgumentObject(types::StackTypeSet *obj);
|
||||
|
@ -323,6 +323,49 @@ types::TypeFailure(JSContext *cx, const char *fmt, ...)
|
||||
// TypeSet
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
TypeSet::isSubset(TypeSet *other)
|
||||
{
|
||||
if ((baseFlags() & other->baseFlags()) != baseFlags())
|
||||
return false;
|
||||
|
||||
if (unknownObject()) {
|
||||
JS_ASSERT(other->unknownObject());
|
||||
} else {
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeObjectKey *obj = getObject(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(obj)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeSet::isSubsetIgnorePrimitives(TypeSet *other)
|
||||
{
|
||||
TypeFlags otherFlags = other->baseFlags() | TYPE_FLAG_PRIMITIVE;
|
||||
if ((baseFlags() & otherFlags) != baseFlags())
|
||||
return false;
|
||||
|
||||
if (unknownObject()) {
|
||||
JS_ASSERT(other->unknownObject());
|
||||
} else {
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeObjectKey *obj = getObject(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(obj)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
|
||||
{
|
||||
@ -1958,21 +2001,9 @@ HeapTypeSet::knownSubset(JSContext *cx, TypeSet *other)
|
||||
{
|
||||
JS_ASSERT(!other->constraintsPurged());
|
||||
|
||||
if ((baseFlags() & other->baseFlags()) != baseFlags())
|
||||
if (!isSubset(other))
|
||||
return false;
|
||||
|
||||
if (unknownObject()) {
|
||||
JS_ASSERT(other->unknownObject());
|
||||
} else {
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeObjectKey *obj = getObject(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(obj)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
addFreeze(cx);
|
||||
|
||||
return true;
|
||||
|
@ -286,6 +286,10 @@ enum {
|
||||
TYPE_FLAG_LAZYARGS = 0x40,
|
||||
TYPE_FLAG_ANYOBJECT = 0x80,
|
||||
|
||||
/* Mask containing all primitives */
|
||||
TYPE_FLAG_PRIMITIVE = TYPE_FLAG_UNDEFINED | TYPE_FLAG_NULL | TYPE_FLAG_BOOLEAN |
|
||||
TYPE_FLAG_INT32 | TYPE_FLAG_DOUBLE | TYPE_FLAG_STRING,
|
||||
|
||||
/* Mask/shift for the number of objects in objectSet */
|
||||
TYPE_FLAG_OBJECT_COUNT_MASK = 0xff00,
|
||||
TYPE_FLAG_OBJECT_COUNT_SHIFT = 8,
|
||||
@ -507,6 +511,13 @@ class TypeSet
|
||||
bool purged() { return !!(flags & TYPE_FLAG_PURGED); }
|
||||
void setPurged() { flags |= TYPE_FLAG_PURGED | TYPE_FLAG_CONSTRAINTS_PURGED; }
|
||||
|
||||
/*
|
||||
* Get whether this type set is known to be a subset of other.
|
||||
* This variant doesn't freeze constraints. That variant is called knownSubset
|
||||
*/
|
||||
bool isSubset(TypeSet *other);
|
||||
bool isSubsetIgnorePrimitives(TypeSet *other);
|
||||
|
||||
inline StackTypeSet *toStackTypeSet();
|
||||
inline HeapTypeSet *toHeapTypeSet();
|
||||
|
||||
@ -620,9 +631,7 @@ class StackTypeSet : public TypeSet
|
||||
bool knownNonStringPrimitive();
|
||||
|
||||
bool knownPrimitiveOrObject() {
|
||||
TypeFlags flags = TYPE_FLAG_UNDEFINED | TYPE_FLAG_NULL | TYPE_FLAG_DOUBLE |
|
||||
TYPE_FLAG_INT32 | TYPE_FLAG_BOOLEAN | TYPE_FLAG_STRING |
|
||||
TYPE_FLAG_ANYOBJECT;
|
||||
TypeFlags flags = TYPE_FLAG_PRIMITIVE | TYPE_FLAG_ANYOBJECT;
|
||||
if (baseFlags() & (~flags & TYPE_FLAG_BASE_MASK))
|
||||
return false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user