зеркало из https://github.com/mozilla/gecko-dev.git
Bug 830269 - Thread the callee typeset through instead of incorrectly recomputing (r=dvander)
This commit is contained in:
Родитель
01c8aaecc5
Коммит
a8964e4fc2
|
@ -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();
|
Загрузка…
Ссылка в новой задаче