Bug 830269 - Thread the callee typeset through instead of incorrectly recomputing (r=dvander)

This commit is contained in:
Shu-yu Guo 2013-01-15 11:12:48 -08:00
Родитель 01c8aaecc5
Коммит a8964e4fc2
3 изменённых файлов: 62 добавлений и 41 удалений

Просмотреть файл

@ -138,11 +138,10 @@ IonBuilder::CFGState::TableSwitch(jsbytecode *exitpc, MTableSwitch *ins)
}
JSFunction *
IonBuilder::getSingleCallTarget(uint32_t argc, jsbytecode *pc)
IonBuilder::getSingleCallTarget(types::StackTypeSet *calleeTypes)
{
AutoAssertNoGC nogc;
types::StackTypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
if (!calleeTypes)
return NULL;
@ -154,10 +153,9 @@ IonBuilder::getSingleCallTarget(uint32_t argc, jsbytecode *pc)
}
uint32_t
IonBuilder::getPolyCallTargets(uint32_t argc, jsbytecode *pc,
IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
AutoObjectVector &targets, uint32_t maxTargets)
{
types::TypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
if (!calleeTypes)
return 0;
@ -3724,9 +3722,10 @@ IonBuilder::jsop_funcall(uint32_t argc)
// argc+2: The native 'call' function.
// If |Function.prototype.call| may be overridden, don't optimize callsite.
RootedFunction native(cx, getSingleCallTarget(argc, pc));
types::StackTypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
RootedFunction native(cx, getSingleCallTarget(calleeTypes));
if (!native || !native->isNative() || native->native() != &js_fun_call)
return makeCall(native, argc, false, false);
return makeCall(native, calleeTypes, argc, false, false);
// Extract call target.
types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
@ -3759,15 +3758,16 @@ IonBuilder::jsop_funcall(uint32_t argc)
}
// Call without inlining.
return makeCall(target, argc, false, false);
return makeCall(target, funTypes, argc, false, false);
}
bool
IonBuilder::jsop_funapply(uint32_t argc)
{
RootedFunction native(cx, getSingleCallTarget(argc, pc));
types::StackTypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
RootedFunction native(cx, getSingleCallTarget(calleeTypes));
if (argc != 2)
return makeCall(native, argc, false, false);
return makeCall(native, calleeTypes, argc, false, false);
// Disable compilation if the second argument to |apply| cannot be guaranteed
// to be either definitely |arguments| or definitely not |arguments|.
@ -3778,7 +3778,7 @@ IonBuilder::jsop_funapply(uint32_t argc)
// Fallback to regular call if arg 2 is not definitely |arguments|.
if (isArgObj != DefinitelyArguments)
return makeCall(native, argc, false, false);
return makeCall(native, calleeTypes, argc, false, false);
if (!native ||
!native->isNative() ||
@ -3867,7 +3867,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
// Pop apply function.
current->pop();
return makeCall(target, false, false, argFunc, thisArg, args);
return makeCall(target, funTypes, false, false, argFunc, thisArg, args);
}
bool
@ -3877,7 +3877,8 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
// Acquire known call target if existent.
AutoObjectVector originals(cx);
uint32_t numTargets = getPolyCallTargets(argc, pc, originals, 4);
types::StackTypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
uint32_t numTargets = calleeTypes ? getPolyCallTargets(calleeTypes, originals, 4) : 0;
types::StackTypeSet *barrier;
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
@ -3922,7 +3923,7 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
if (numTargets == 1)
target = targets[0]->toFunction();
return makeCallBarrier(target, argc, constructing, hasClones, types, barrier);
return makeCallBarrier(target, calleeTypes, argc, constructing, hasClones, types, barrier);
}
MDefinition *
@ -4060,19 +4061,20 @@ IonBuilder::popFormals(uint32_t argc, MDefinition **fun, MPassArg **thisArg,
}
MCall *
IonBuilder::makeCallHelper(HandleFunction target, uint32_t argc, bool constructing,
bool cloneAtCallsite)
IonBuilder::makeCallHelper(HandleFunction target, types::StackTypeSet *calleeTypes,
uint32_t argc, bool constructing, bool cloneAtCallsite)
{
Vector<MPassArg *> args(cx);
MPassArg *thisArg;
MDefinition *fun;
popFormals(argc, &fun, &thisArg, &args);
return makeCallHelper(target, constructing, cloneAtCallsite, fun, thisArg, args);
return makeCallHelper(target, calleeTypes, constructing, cloneAtCallsite, fun, thisArg, args);
}
MCall *
IonBuilder::makeCallHelper(HandleFunction target, bool constructing, bool cloneAtCallsite,
IonBuilder::makeCallHelper(HandleFunction target, types::StackTypeSet *calleeTypes,
bool constructing, bool cloneAtCallsite,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args)
{
// This function may be called with mutated stack.
@ -4086,8 +4088,7 @@ IonBuilder::makeCallHelper(HandleFunction target, bool constructing, bool cloneA
if (target && !target->isNative())
targetArgs = Max<uint32_t>(target->nargs, argc);
MCall *call = MCall::New(target, targetArgs + 1, argc, constructing,
target ? NULL : oracle->getCallTarget(script(), argc, pc));
MCall *call = MCall::New(target, targetArgs + 1, argc, constructing, calleeTypes);
if (!call)
return NULL;
@ -4178,8 +4179,8 @@ AdjustTypeBarrierForDOMCall(const JSJitInfo* jitinfo, types::StackTypeSet *types
}
bool
IonBuilder::makeCallBarrier(HandleFunction target, uint32_t argc,
bool constructing, bool cloneAtCallsite,
IonBuilder::makeCallBarrier(HandleFunction target, types::StackTypeSet *calleeTypes,
uint32_t argc, bool constructing, bool cloneAtCallsite,
types::StackTypeSet *types,
types::StackTypeSet *barrier)
{
@ -4188,18 +4189,20 @@ IonBuilder::makeCallBarrier(HandleFunction target, uint32_t argc,
MDefinition *fun;
popFormals(argc, &fun, &thisArg, &args);
return makeCallBarrier(target, constructing, cloneAtCallsite,
return makeCallBarrier(target, calleeTypes, constructing, cloneAtCallsite,
fun, thisArg, args, types, barrier);
}
bool
IonBuilder::makeCallBarrier(HandleFunction target, bool constructing, bool cloneAtCallsite,
IonBuilder::makeCallBarrier(HandleFunction target, types::StackTypeSet *calleeTypes,
bool constructing, bool cloneAtCallsite,
MDefinition *fun, MPassArg *thisArg,
Vector<MPassArg *> &args,
types::StackTypeSet *types,
types::StackTypeSet *barrier)
{
MCall *call = makeCallHelper(target, constructing, cloneAtCallsite, fun, thisArg, args);
MCall *call = makeCallHelper(target, calleeTypes, constructing, cloneAtCallsite,
fun, thisArg, args);
if (!call)
return false;
@ -4217,24 +4220,26 @@ IonBuilder::makeCallBarrier(HandleFunction target, bool constructing, bool clone
}
bool
IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing, bool cloneAtCallsite)
IonBuilder::makeCall(HandleFunction target, types::StackTypeSet *calleeTypes,
uint32_t argc, bool constructing, bool cloneAtCallsite)
{
Vector<MPassArg *> args(cx);
MPassArg *thisArg;
MDefinition *fun;
popFormals(argc, &fun, &thisArg, &args);
return makeCall(target, constructing, cloneAtCallsite, fun, thisArg, args);
return makeCall(target, calleeTypes, constructing, cloneAtCallsite, fun, thisArg, args);
}
bool
IonBuilder::makeCall(HandleFunction target, bool constructing, bool cloneAtCallsite,
IonBuilder::makeCall(HandleFunction target, types::StackTypeSet *calleeTypes,
bool constructing, bool cloneAtCallsite,
MDefinition *fun, MPassArg *thisArg,
Vector<MPassArg*> &args)
{
types::StackTypeSet *barrier;
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
return makeCallBarrier(target, constructing, cloneAtCallsite,
return makeCallBarrier(target, calleeTypes, constructing, cloneAtCallsite,
fun, thisArg, args, types, barrier);
}
@ -6352,7 +6357,7 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, HandleId id, types::StackTypeS
current->add(wrapper);
current->push(wrapper);
if (!makeCallBarrier(getter, 0, false, false, types, barrier))
if (!makeCallBarrier(getter, unaryTypes.inTypes, 0, false, false, types, barrier))
return false;
*emitted = true;
@ -6518,7 +6523,7 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
// Call the setter. Note that we have to push the original value, not
// the setter's return value.
MCall *call = makeCallHelper(setter, 1, false, false);
MCall *call = makeCallHelper(setter, types, 1, false, false);
if (!call)
return false;

Просмотреть файл

@ -187,8 +187,8 @@ class IonBuilder : public MIRGenerator
return js_IonOptions.inlining;
}
JSFunction *getSingleCallTarget(uint32_t argc, jsbytecode *pc);
unsigned getPolyCallTargets(uint32_t argc, jsbytecode *pc,
JSFunction *getSingleCallTarget(types::StackTypeSet *calleeTypes);
unsigned getPolyCallTargets(types::StackTypeSet *calleeTypes,
AutoObjectVector &targets, uint32_t maxTargets);
bool canInlineTarget(JSFunction *target);
@ -428,18 +428,22 @@ class IonBuilder : public MIRGenerator
MDefinition *makeCallsiteClone(HandleFunction target, MDefinition *fun);
void popFormals(uint32_t argc, MDefinition **fun, MPassArg **thisArg,
Vector<MPassArg *> *args);
MCall *makeCallHelper(HandleFunction target, bool constructing, bool cloneAtCallsite,
MCall *makeCallHelper(HandleFunction target, types::StackTypeSet *calleeTypes,
bool constructing, bool cloneAtCallsite,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args);
MCall *makeCallHelper(HandleFunction target, uint32_t argc, bool constructing,
bool cloneAtCallsite);
bool makeCallBarrier(HandleFunction target, uint32_t argc, bool constructing,
bool cloneAtCallsite, types::StackTypeSet *types,
types::StackTypeSet *barrier);
bool makeCallBarrier(HandleFunction target, bool constructing, bool cloneAtCallsite,
MCall *makeCallHelper(HandleFunction target, types::StackTypeSet *calleeTypes,
uint32_t argc, bool constructing, bool cloneAtCallsite);
bool makeCallBarrier(HandleFunction target, types::StackTypeSet *calleeTypes,
uint32_t argc, bool constructing, bool cloneAtCallsite,
types::StackTypeSet *types, types::StackTypeSet *barrier);
bool makeCallBarrier(HandleFunction target, types::StackTypeSet *calleeTypes,
bool constructing, bool cloneAtCallsite,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args,
types::StackTypeSet *types, types::StackTypeSet *barrier);
bool makeCall(HandleFunction target, uint32_t argc, bool constructing, bool cloneAtCallsite);
bool makeCall(HandleFunction target, bool constructing, bool cloneAtCallsite,
bool makeCall(HandleFunction target, types::StackTypeSet *calleeTypes,
uint32_t argc, bool constructing, bool cloneAtCallsite);
bool makeCall(HandleFunction target, types::StackTypeSet *calleeTypes,
bool constructing, bool cloneAtCallsite,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args);
inline bool TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types,

Просмотреть файл

@ -0,0 +1,12 @@
function f(g,y,z,w) {
return g.apply(undefined, arguments);
}
function outer() {
var g = function() {};
for (var i = 0; i < 20000; i++)
f(g,2,3,4,5);
f(g,2,3,4,5);
}
outer();