Bug 934500 - Don't eagerly create callsite clones in IonBuilder, r=shu.

This commit is contained in:
Brian Hackett 2013-11-05 18:00:44 -08:00
Родитель 7afcc444c7
Коммит 280f31f856
5 изменённых файлов: 41 добавлений и 41 удалений

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

@ -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);