зеркало из https://github.com/mozilla/gecko-dev.git
Bug 934500 - Don't eagerly create callsite clones in IonBuilder, r=shu.
This commit is contained in:
Родитель
7afcc444c7
Коммит
280f31f856
|
@ -4963,19 +4963,17 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
|
|||
}
|
||||
JS_ASSERT_IF(gotLambda, originals.length() <= 1);
|
||||
|
||||
// If any call targets need to be cloned, clone them. Keep track of the
|
||||
// originals as we need to case on them for poly inline.
|
||||
// If any call targets need to be cloned, look for existing clones to use.
|
||||
// Keep track of the originals as we need to case on them for poly inline.
|
||||
bool hasClones = false;
|
||||
ObjectVector targets;
|
||||
RootedFunction fun(cx);
|
||||
RootedScript scriptRoot(cx, script());
|
||||
for (uint32_t i = 0; i < originals.length(); i++) {
|
||||
fun = &originals[i]->as<JSFunction>();
|
||||
JSFunction *fun = &originals[i]->as<JSFunction>();
|
||||
if (fun->hasScript() && fun->nonLazyScript()->shouldCloneAtCallsite) {
|
||||
fun = CloneFunctionAtCallsite(cx, fun, scriptRoot, pc);
|
||||
if (!fun)
|
||||
return false;
|
||||
hasClones = true;
|
||||
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, fun, script(), pc)) {
|
||||
fun = clone;
|
||||
hasClones = true;
|
||||
}
|
||||
}
|
||||
if (!targets.append(fun))
|
||||
return false;
|
||||
|
|
|
@ -583,7 +583,7 @@ class IonBuilder : public MIRGenerator
|
|||
InliningStatus inlineNewParallelArray(CallInfo &callInfo);
|
||||
InliningStatus inlineParallelArray(CallInfo &callInfo);
|
||||
InliningStatus inlineParallelArrayTail(CallInfo &callInfo,
|
||||
HandleFunction target,
|
||||
JSFunction *target,
|
||||
MDefinition *ctor,
|
||||
types::TemporaryTypeSet *ctorTypes,
|
||||
uint32_t discards);
|
||||
|
|
|
@ -1195,14 +1195,12 @@ IonBuilder::inlineNewParallelArray(CallInfo &callInfo)
|
|||
|
||||
types::TemporaryTypeSet *ctorTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
JSObject *targetObj = ctorTypes ? ctorTypes->getSingleton() : nullptr;
|
||||
RootedFunction target(cx);
|
||||
JSFunction *target = nullptr;
|
||||
if (targetObj && targetObj->is<JSFunction>())
|
||||
target = &targetObj->as<JSFunction>();
|
||||
if (target && target->isInterpreted() && target->nonLazyScript()->shouldCloneAtCallsite) {
|
||||
RootedScript scriptRoot(cx, script());
|
||||
target = CloneFunctionAtCallsite(cx, target, scriptRoot, pc);
|
||||
if (!target)
|
||||
return InliningStatus_Error;
|
||||
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, target, script(), pc))
|
||||
target = clone;
|
||||
}
|
||||
MDefinition *ctor = makeCallsiteClone(
|
||||
target,
|
||||
|
@ -1220,15 +1218,13 @@ IonBuilder::inlineParallelArray(CallInfo &callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
|
||||
uint32_t argc = callInfo.argc();
|
||||
RootedFunction target(cx, ParallelArrayObject::getConstructor(cx, argc));
|
||||
JSFunction *target = ParallelArrayObject::getConstructor(cx, argc);
|
||||
if (!target)
|
||||
return InliningStatus_Error;
|
||||
|
||||
JS_ASSERT(target->nonLazyScript()->shouldCloneAtCallsite);
|
||||
RootedScript script(cx, script_);
|
||||
target = CloneFunctionAtCallsite(cx, target, script, pc);
|
||||
if (!target)
|
||||
return InliningStatus_Error;
|
||||
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, target, script(), pc))
|
||||
target = clone;
|
||||
|
||||
MConstant *ctor = MConstant::New(ObjectValue(*target));
|
||||
current->add(ctor);
|
||||
|
@ -1238,7 +1234,7 @@ IonBuilder::inlineParallelArray(CallInfo &callInfo)
|
|||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineParallelArrayTail(CallInfo &callInfo,
|
||||
HandleFunction target,
|
||||
JSFunction *target,
|
||||
MDefinition *ctor,
|
||||
types::TemporaryTypeSet *ctorTypes,
|
||||
uint32_t discards)
|
||||
|
|
|
@ -110,9 +110,10 @@ JSCompartment::sweepCallsiteClones()
|
|||
}
|
||||
|
||||
JSFunction *
|
||||
js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
|
||||
js::ExistingCloneFunctionAtCallsite(JSCompartment *comp, JSFunction *fun,
|
||||
JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
JS_ASSERT(comp->zone()->types.inferenceEnabled);
|
||||
JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite);
|
||||
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
|
||||
JS_ASSERT(types::UseNewTypeForClone(fun));
|
||||
|
@ -126,23 +127,25 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri
|
|||
typedef CallsiteCloneKey Key;
|
||||
typedef CallsiteCloneTable Table;
|
||||
|
||||
Table &table = cx->compartment()->callsiteClones;
|
||||
if (!table.initialized() && !table.init())
|
||||
Table &table = comp->callsiteClones;
|
||||
if (!table.initialized())
|
||||
return nullptr;
|
||||
|
||||
uint32_t offset = pc - script->code;
|
||||
void* originalScript = script;
|
||||
void* originalFun = fun;
|
||||
SkipRoot skipScript(cx, &originalScript);
|
||||
SkipRoot skipFun(cx, &originalFun);
|
||||
|
||||
Table::AddPtr p = table.lookupForAdd(Key(fun, script, offset));
|
||||
SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
|
||||
Table::Ptr p = table.lookup(Key(fun, script, pc - script->code));
|
||||
if (p)
|
||||
return p->value;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
|
||||
{
|
||||
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(cx->compartment(), fun, script, pc))
|
||||
return clone;
|
||||
|
||||
RootedObject parent(cx, fun->environment());
|
||||
RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent));
|
||||
JSFunction *clone = CloneFunctionObject(cx, fun, parent);
|
||||
if (!clone)
|
||||
return nullptr;
|
||||
|
||||
|
@ -154,15 +157,14 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri
|
|||
clone->nonLazyScript()->isCallsiteClone = true;
|
||||
clone->nonLazyScript()->setOriginalFunctionObject(fun);
|
||||
|
||||
Key key(fun, script, offset);
|
||||
typedef CallsiteCloneKey Key;
|
||||
typedef CallsiteCloneTable Table;
|
||||
|
||||
/* Recalculate the hash if script or fun have been moved. */
|
||||
if (script != originalScript || fun != originalFun) {
|
||||
p = table.lookupForAdd(key);
|
||||
JS_ASSERT(!p);
|
||||
}
|
||||
Table &table = cx->compartment()->callsiteClones;
|
||||
if (!table.initialized() && !table.init())
|
||||
return nullptr;
|
||||
|
||||
if (!table.relookupOrAdd(p, key, clone.get()))
|
||||
if (!table.putNew(Key(fun, script, pc - script->code), clone))
|
||||
return nullptr;
|
||||
|
||||
return clone;
|
||||
|
|
|
@ -64,6 +64,10 @@ typedef HashMap<CallsiteCloneKey,
|
|||
CallsiteCloneKey,
|
||||
SystemAllocPolicy> CallsiteCloneTable;
|
||||
|
||||
JSFunction *
|
||||
ExistingCloneFunctionAtCallsite(JSCompartment *comp, JSFunction *fun,
|
||||
JSScript *script, jsbytecode *pc);
|
||||
|
||||
JSFunction *CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
|
||||
HandleScript script, jsbytecode *pc);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче