зеркало из 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);
|
JS_ASSERT_IF(gotLambda, originals.length() <= 1);
|
||||||
|
|
||||||
// If any call targets need to be cloned, clone them. Keep track of the
|
// If any call targets need to be cloned, look for existing clones to use.
|
||||||
// originals as we need to case on them for poly inline.
|
// Keep track of the originals as we need to case on them for poly inline.
|
||||||
bool hasClones = false;
|
bool hasClones = false;
|
||||||
ObjectVector targets;
|
ObjectVector targets;
|
||||||
RootedFunction fun(cx);
|
|
||||||
RootedScript scriptRoot(cx, script());
|
|
||||||
for (uint32_t i = 0; i < originals.length(); i++) {
|
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) {
|
if (fun->hasScript() && fun->nonLazyScript()->shouldCloneAtCallsite) {
|
||||||
fun = CloneFunctionAtCallsite(cx, fun, scriptRoot, pc);
|
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, fun, script(), pc)) {
|
||||||
if (!fun)
|
fun = clone;
|
||||||
return false;
|
hasClones = true;
|
||||||
hasClones = true;
|
}
|
||||||
}
|
}
|
||||||
if (!targets.append(fun))
|
if (!targets.append(fun))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -583,7 +583,7 @@ class IonBuilder : public MIRGenerator
|
||||||
InliningStatus inlineNewParallelArray(CallInfo &callInfo);
|
InliningStatus inlineNewParallelArray(CallInfo &callInfo);
|
||||||
InliningStatus inlineParallelArray(CallInfo &callInfo);
|
InliningStatus inlineParallelArray(CallInfo &callInfo);
|
||||||
InliningStatus inlineParallelArrayTail(CallInfo &callInfo,
|
InliningStatus inlineParallelArrayTail(CallInfo &callInfo,
|
||||||
HandleFunction target,
|
JSFunction *target,
|
||||||
MDefinition *ctor,
|
MDefinition *ctor,
|
||||||
types::TemporaryTypeSet *ctorTypes,
|
types::TemporaryTypeSet *ctorTypes,
|
||||||
uint32_t discards);
|
uint32_t discards);
|
||||||
|
|
|
@ -1195,14 +1195,12 @@ IonBuilder::inlineNewParallelArray(CallInfo &callInfo)
|
||||||
|
|
||||||
types::TemporaryTypeSet *ctorTypes = callInfo.getArg(0)->resultTypeSet();
|
types::TemporaryTypeSet *ctorTypes = callInfo.getArg(0)->resultTypeSet();
|
||||||
JSObject *targetObj = ctorTypes ? ctorTypes->getSingleton() : nullptr;
|
JSObject *targetObj = ctorTypes ? ctorTypes->getSingleton() : nullptr;
|
||||||
RootedFunction target(cx);
|
JSFunction *target = nullptr;
|
||||||
if (targetObj && targetObj->is<JSFunction>())
|
if (targetObj && targetObj->is<JSFunction>())
|
||||||
target = &targetObj->as<JSFunction>();
|
target = &targetObj->as<JSFunction>();
|
||||||
if (target && target->isInterpreted() && target->nonLazyScript()->shouldCloneAtCallsite) {
|
if (target && target->isInterpreted() && target->nonLazyScript()->shouldCloneAtCallsite) {
|
||||||
RootedScript scriptRoot(cx, script());
|
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, target, script(), pc))
|
||||||
target = CloneFunctionAtCallsite(cx, target, scriptRoot, pc);
|
target = clone;
|
||||||
if (!target)
|
|
||||||
return InliningStatus_Error;
|
|
||||||
}
|
}
|
||||||
MDefinition *ctor = makeCallsiteClone(
|
MDefinition *ctor = makeCallsiteClone(
|
||||||
target,
|
target,
|
||||||
|
@ -1220,15 +1218,13 @@ IonBuilder::inlineParallelArray(CallInfo &callInfo)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
uint32_t argc = callInfo.argc();
|
uint32_t argc = callInfo.argc();
|
||||||
RootedFunction target(cx, ParallelArrayObject::getConstructor(cx, argc));
|
JSFunction *target = ParallelArrayObject::getConstructor(cx, argc);
|
||||||
if (!target)
|
if (!target)
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
|
|
||||||
JS_ASSERT(target->nonLazyScript()->shouldCloneAtCallsite);
|
JS_ASSERT(target->nonLazyScript()->shouldCloneAtCallsite);
|
||||||
RootedScript script(cx, script_);
|
if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, target, script(), pc))
|
||||||
target = CloneFunctionAtCallsite(cx, target, script, pc);
|
target = clone;
|
||||||
if (!target)
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MConstant *ctor = MConstant::New(ObjectValue(*target));
|
MConstant *ctor = MConstant::New(ObjectValue(*target));
|
||||||
current->add(ctor);
|
current->add(ctor);
|
||||||
|
@ -1238,7 +1234,7 @@ IonBuilder::inlineParallelArray(CallInfo &callInfo)
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineParallelArrayTail(CallInfo &callInfo,
|
IonBuilder::inlineParallelArrayTail(CallInfo &callInfo,
|
||||||
HandleFunction target,
|
JSFunction *target,
|
||||||
MDefinition *ctor,
|
MDefinition *ctor,
|
||||||
types::TemporaryTypeSet *ctorTypes,
|
types::TemporaryTypeSet *ctorTypes,
|
||||||
uint32_t discards)
|
uint32_t discards)
|
||||||
|
|
|
@ -110,9 +110,10 @@ JSCompartment::sweepCallsiteClones()
|
||||||
}
|
}
|
||||||
|
|
||||||
JSFunction *
|
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()->shouldCloneAtCallsite);
|
||||||
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
|
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
|
||||||
JS_ASSERT(types::UseNewTypeForClone(fun));
|
JS_ASSERT(types::UseNewTypeForClone(fun));
|
||||||
|
@ -126,23 +127,25 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri
|
||||||
typedef CallsiteCloneKey Key;
|
typedef CallsiteCloneKey Key;
|
||||||
typedef CallsiteCloneTable Table;
|
typedef CallsiteCloneTable Table;
|
||||||
|
|
||||||
Table &table = cx->compartment()->callsiteClones;
|
Table &table = comp->callsiteClones;
|
||||||
if (!table.initialized() && !table.init())
|
if (!table.initialized())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
uint32_t offset = pc - script->code;
|
Table::Ptr p = table.lookup(Key(fun, script, 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. */
|
|
||||||
if (p)
|
if (p)
|
||||||
return p->value;
|
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());
|
RootedObject parent(cx, fun->environment());
|
||||||
RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent));
|
JSFunction *clone = CloneFunctionObject(cx, fun, parent);
|
||||||
if (!clone)
|
if (!clone)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -154,15 +157,14 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri
|
||||||
clone->nonLazyScript()->isCallsiteClone = true;
|
clone->nonLazyScript()->isCallsiteClone = true;
|
||||||
clone->nonLazyScript()->setOriginalFunctionObject(fun);
|
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. */
|
Table &table = cx->compartment()->callsiteClones;
|
||||||
if (script != originalScript || fun != originalFun) {
|
if (!table.initialized() && !table.init())
|
||||||
p = table.lookupForAdd(key);
|
return nullptr;
|
||||||
JS_ASSERT(!p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!table.relookupOrAdd(p, key, clone.get()))
|
if (!table.putNew(Key(fun, script, pc - script->code), clone))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
|
|
@ -64,6 +64,10 @@ typedef HashMap<CallsiteCloneKey,
|
||||||
CallsiteCloneKey,
|
CallsiteCloneKey,
|
||||||
SystemAllocPolicy> CallsiteCloneTable;
|
SystemAllocPolicy> CallsiteCloneTable;
|
||||||
|
|
||||||
|
JSFunction *
|
||||||
|
ExistingCloneFunctionAtCallsite(JSCompartment *comp, JSFunction *fun,
|
||||||
|
JSScript *script, jsbytecode *pc);
|
||||||
|
|
||||||
JSFunction *CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
|
JSFunction *CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
|
||||||
HandleScript script, jsbytecode *pc);
|
HandleScript script, jsbytecode *pc);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче