Backed out 4 changesets (bug 826148) because of test failures

Backed out changeset e520c411aed6 (bug 826148)
Backed out changeset 1db5b4e59649 (bug 826148)
Backed out changeset 57bf735f3e18 (bug 826148)
Backed out changeset b659dc17b164 (bug 826148)
This commit is contained in:
Ehsan Akhgari 2013-01-11 00:05:36 -05:00
Родитель f53138b7aa
Коммит 1e93b24dfe
32 изменённых файлов: 97 добавлений и 762 удалений

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

@ -3844,8 +3844,6 @@ class OutOfLineCache : public OutOfLineCodeBase<CodeGenerator>
return codegen->visitOutOfLineBindNameCache(this);
case LInstruction::LOp_GetNameCache:
return codegen->visitOutOfLineGetNameCache(this);
case LInstruction::LOp_CallsiteCloneCache:
return codegen->visitOutOfLineCallsiteCloneCache(this);
default:
JS_NOT_REACHED("Bad instruction");
return false;
@ -3885,41 +3883,6 @@ CodeGenerator::visitCache(LInstruction *ins)
return true;
}
typedef JSObject *(*CallsiteCloneCacheFn)(JSContext *, size_t, HandleObject);
static const VMFunction CallsiteCloneCacheInfo =
FunctionInfo<CallsiteCloneCacheFn>(CallsiteCloneCache);
bool
CodeGenerator::visitOutOfLineCallsiteCloneCache(OutOfLineCache *ool)
{
LCallsiteCloneCache *lir = ool->cache()->toCallsiteCloneCache();
const MCallsiteCloneCache *mir = lir->mir();
Register callee = ToRegister(lir->callee());
RegisterSet liveRegs = lir->safepoint()->liveRegs();
Register output = ToRegister(lir->output());
IonCacheCallsiteClone cache(ool->getInlineJump(), ool->getInlineLabel(),
masm.labelForPatch(), liveRegs,
callee, mir->block()->info().script(), mir->callPc(), output);
JS_ASSERT(!mir->resumePoint());
size_t cacheIndex = allocateCache(cache);
saveLive(lir);
pushArg(callee);
pushArg(Imm32(cacheIndex));
if (!callVM(CallsiteCloneCacheInfo, lir))
return false;
masm.storeCallResult(output);
restoreLive(lir);
masm.jump(ool->rejoin());
return true;
}
typedef bool (*GetNameCacheFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
static const VMFunction GetNameCacheInfo =
FunctionInfo<GetNameCacheFn>(GetNameCache);

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

@ -201,7 +201,6 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitOutOfLineSetPropertyCache(OutOfLineCache *ool);
bool visitOutOfLineBindNameCache(OutOfLineCache *ool);
bool visitOutOfLineGetNameCache(OutOfLineCache *ool);
bool visitOutOfLineCallsiteCloneCache(OutOfLineCache *ool);
bool visitGetPropertyCacheV(LGetPropertyCacheV *ins) {
return visitCache(ins);
@ -224,9 +223,6 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitGetNameCache(LGetNameCache *ins) {
return visitCache(ins);
}
bool visitCallsiteCloneCache(LCallsiteCloneCache *ins) {
return visitCache(ins);
}
private:
bool visitCache(LInstruction *load);

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

@ -3109,7 +3109,8 @@ IonBuilder::checkInlineableGetPropertyCache(uint32_t argc)
}
MPolyInlineDispatch *
IonBuilder::makePolyInlineDispatch(JSContext *cx, int argc, MGetPropertyCache *getPropCache,
IonBuilder::makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
MGetPropertyCache *getPropCache,
types::StackTypeSet *types, types::StackTypeSet *barrier,
MBasicBlock *bottom,
Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns)
@ -3206,8 +3207,7 @@ IonBuilder::makePolyInlineDispatch(JSContext *cx, int argc, MGetPropertyCache *g
fallbackBlock->end(MGoto::New(fallbackEndBlock));
// Create Call
MCall *call = MCall::New(NULL, argc + 1, argc, false,
oracle->getCallTarget(script(), argc, pc));
MCall *call = MCall::New(NULL, argc + 1, argc, false);
if (!call)
return NULL;
@ -3249,8 +3249,7 @@ IonBuilder::makePolyInlineDispatch(JSContext *cx, int argc, MGetPropertyCache *g
}
bool
IonBuilder::inlineScriptedCall(AutoObjectVector &targets, AutoObjectVector &originals,
uint32_t argc, bool constructing,
IonBuilder::inlineScriptedCall(AutoObjectVector &targets, uint32_t argc, bool constructing,
types::StackTypeSet *types, types::StackTypeSet *barrier)
{
#ifdef DEBUG
@ -3290,7 +3289,7 @@ IonBuilder::inlineScriptedCall(AutoObjectVector &targets, AutoObjectVector &orig
int numCases = inlinePropTable->numEntries();
IonSpew(IonSpew_Inlining, "Got inlineable property cache with %d cases", numCases);
inlinePropTable->trimToAndMaybePatchTargets(targets, originals);
inlinePropTable->trimToTargets(targets);
// Trim the cases based on those that match the targets at this call site.
IonSpew(IonSpew_Inlining, "%d inlineable cases left after trimming to %d targets",
@ -3340,18 +3339,14 @@ IonBuilder::inlineScriptedCall(AutoObjectVector &targets, AutoObjectVector &orig
// In the polymorphic case, we end the current block with a MPolyInlineDispatch instruction.
// Create a PolyInlineDispatch instruction for this call site
MPolyInlineDispatch *disp = makePolyInlineDispatch(cx, argc, getPropCache, types, barrier,
bottom, retvalDefns);
MPolyInlineDispatch *disp = makePolyInlineDispatch(cx, targets, argc, getPropCache,
types, barrier, bottom, retvalDefns);
if (!disp)
return false;
// It's guaranteed that targets.length() == originals.length()
for (size_t i = 0; i < targets.length(); i++) {
// Create an MConstant for the function. Note that we guard on the
// original function pointer, even if we have a clone, as we only
// clone at the callsite, so guarding on the clone would be
// guaranteed to fail.
JSFunction *func = originals[i]->toFunction();
// Create an MConstant for the function
JSFunction *func = targets[i]->toFunction();
RootedFunction target(cx, func);
MConstant *constFun = MConstant::New(ObjectValue(*func));
// Create new entry block for the inlined callee graph.
@ -3698,21 +3693,6 @@ IonBuilder::createThis(HandleFunction target, MDefinition *callee)
return createThisScripted(callee);
}
bool
IonBuilder::anyFunctionIsCloneAtCallsite(types::StackTypeSet *funTypes)
{
uint32_t count = funTypes->getObjectCount();
if (count < 1)
return false;
for (uint32_t i = 0; i < count; i++) {
JSObject *obj = funTypes->getSingleObject(i);
if (obj->isFunction() && obj->toFunction()->isCloneAtCallsite())
return true;
}
return false;
}
bool
IonBuilder::jsop_funcall(uint32_t argc)
{
@ -3726,7 +3706,7 @@ IonBuilder::jsop_funcall(uint32_t argc)
// If |Function.prototype.call| may be overridden, don't optimize callsite.
RootedFunction native(cx, getSingleCallTarget(argc, pc));
if (!native || !native->isNative() || native->native() != &js_fun_call)
return makeCall(native, argc, false, false);
return makeCall(native, argc, false);
// Extract call target.
types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
@ -3759,7 +3739,7 @@ IonBuilder::jsop_funcall(uint32_t argc)
}
// Call without inlining.
return makeCall(target, argc, false, false);
return makeCall(target, argc, false);
}
bool
@ -3767,7 +3747,7 @@ IonBuilder::jsop_funapply(uint32_t argc)
{
RootedFunction native(cx, getSingleCallTarget(argc, pc));
if (argc != 2)
return makeCall(native, argc, false, false);
return makeCall(native, argc, false);
// Disable compilation if the second argument to |apply| cannot be guaranteed
// to be either definitely |arguments| or definitely not |arguments|.
@ -3778,7 +3758,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, argc, false);
if (!native ||
!native->isNative() ||
@ -3867,7 +3847,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
// Pop apply function.
current->pop();
return makeCall(target, false, false, argFunc, thisArg, args);
return makeCall(target, false, argFunc, thisArg, args);
}
bool
@ -3876,29 +3856,11 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
AssertCanGC();
// Acquire known call target if existent.
AutoObjectVector originals(cx);
uint32_t numTargets = getPolyCallTargets(argc, pc, originals, 4);
AutoObjectVector targets(cx);
uint32_t numTargets = getPolyCallTargets(argc, pc, targets, 4);
types::StackTypeSet *barrier;
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
// 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.
bool hasClones = false;
AutoObjectVector targets(cx);
RootedFunction fun(cx);
RootedScript scriptRoot(cx, script());
for (uint32_t i = 0; i < numTargets; i++) {
fun = originals[i]->toFunction();
if (fun->isCloneAtCallsite()) {
fun = CloneFunctionAtCallsite(cx, fun, scriptRoot, pc);
if (!fun)
return false;
hasClones = true;
}
if (!targets.append(fun))
return false;
}
// Attempt to inline native and scripted functions.
if (inliningEnabled()) {
// Inline a single native call if possible.
@ -3915,34 +3877,14 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
}
if (numTargets > 0 && makeInliningDecision(targets, argc))
return inlineScriptedCall(targets, originals, argc, constructing, types, barrier);
return inlineScriptedCall(targets, argc, constructing, types, barrier);
}
RootedFunction target(cx, NULL);
if (numTargets == 1)
target = targets[0]->toFunction();
return makeCallBarrier(target, argc, constructing, hasClones, types, barrier);
}
MDefinition *
IonBuilder::makeCallsiteClone(HandleFunction target, MDefinition *fun)
{
// Bake in the clone eagerly if we have a known target. We have arrived here
// because TI told us that the known target is a should-clone-at-callsite
// function, which means that target already is the clone.
if (target) {
MConstant *constant = MConstant::New(ObjectValue(*target));
current->add(constant);
return constant;
}
// Add a callsite clone IC if we have multiple targets. Note that we
// should have checked already that at least some targets are marked as
// should-clone-at-callsite.
MCallsiteCloneCache *clone = MCallsiteCloneCache::New(fun, pc);
current->add(clone);
return clone;
return makeCallBarrier(target, argc, constructing, types, barrier);
}
static bool
@ -4060,19 +4002,18 @@ 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, uint32_t argc, bool constructing)
{
Vector<MPassArg *> args(cx);
MPassArg *thisArg;
MDefinition *fun;
popFormals(argc, &fun, &thisArg, &args);
return makeCallHelper(target, constructing, cloneAtCallsite, fun, thisArg, args);
return makeCallHelper(target, constructing, fun, thisArg, args);
}
MCall *
IonBuilder::makeCallHelper(HandleFunction target, bool constructing, bool cloneAtCallsite,
IonBuilder::makeCallHelper(HandleFunction target, bool constructing,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args)
{
// This function may be called with mutated stack.
@ -4086,8 +4027,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);
if (!call)
return NULL;
@ -4131,11 +4071,6 @@ IonBuilder::makeCallHelper(HandleFunction target, bool constructing, bool cloneA
// Pass |this| and function.
call->addArg(0, thisArg);
// Add a callsite clone IC for multiple targets which all should be
// callsite cloned, or bake in the clone for a single target.
if (cloneAtCallsite)
fun = makeCallsiteClone(target, fun);
if (target && JSOp(*pc) == JSOP_CALL) {
// We know we have a single call target. Check whether the "this" types
// are DOM types and our function a DOM function, and if so flag the
@ -4149,7 +4084,6 @@ IonBuilder::makeCallHelper(HandleFunction target, bool constructing, bool cloneA
call->setDOMFunction();
}
}
call->initFunction(fun);
current->add(call);
@ -4179,7 +4113,7 @@ AdjustTypeBarrierForDOMCall(const JSJitInfo* jitinfo, types::StackTypeSet *types
bool
IonBuilder::makeCallBarrier(HandleFunction target, uint32_t argc,
bool constructing, bool cloneAtCallsite,
bool constructing,
types::StackTypeSet *types,
types::StackTypeSet *barrier)
{
@ -4188,18 +4122,17 @@ IonBuilder::makeCallBarrier(HandleFunction target, uint32_t argc,
MDefinition *fun;
popFormals(argc, &fun, &thisArg, &args);
return makeCallBarrier(target, constructing, cloneAtCallsite,
fun, thisArg, args, types, barrier);
return makeCallBarrier(target, constructing, fun, thisArg, args, types, barrier);
}
bool
IonBuilder::makeCallBarrier(HandleFunction target, bool constructing, bool cloneAtCallsite,
IonBuilder::makeCallBarrier(HandleFunction target, bool constructing,
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, constructing, fun, thisArg, args);
if (!call)
return false;
@ -4217,25 +4150,24 @@ IonBuilder::makeCallBarrier(HandleFunction target, bool constructing, bool clone
}
bool
IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing, bool cloneAtCallsite)
IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing)
{
Vector<MPassArg *> args(cx);
MPassArg *thisArg;
MDefinition *fun;
popFormals(argc, &fun, &thisArg, &args);
return makeCall(target, constructing, cloneAtCallsite, fun, thisArg, args);
return makeCall(target, constructing, fun, thisArg, args);
}
bool
IonBuilder::makeCall(HandleFunction target, bool constructing, bool cloneAtCallsite,
IonBuilder::makeCall(HandleFunction target, bool constructing,
MDefinition *fun, MPassArg *thisArg,
Vector<MPassArg*> &args)
{
types::StackTypeSet *barrier;
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
return makeCallBarrier(target, constructing, cloneAtCallsite,
fun, thisArg, args, types, barrier);
return makeCallBarrier(target, constructing, fun, thisArg, args, types, barrier);
}
bool
@ -6352,7 +6284,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, 0, false, types, barrier))
return false;
*emitted = true;
@ -6518,7 +6450,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, 1, false);
if (!call)
return false;

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

@ -419,27 +419,22 @@ class IonBuilder : public MIRGenerator
bool jsop_call_inline(HandleFunction callee, uint32_t argc, bool constructing,
MConstant *constFun, MBasicBlock *bottom,
Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns);
bool inlineScriptedCall(AutoObjectVector &targets, AutoObjectVector &originals,
uint32_t argc, bool constructing,
bool inlineScriptedCall(AutoObjectVector &targets, uint32_t argc, bool constructing,
types::StackTypeSet *types, types::StackTypeSet *barrier);
bool makeInliningDecision(AutoObjectVector &targets, uint32_t argc);
bool anyFunctionIsCloneAtCallsite(types::StackTypeSet *funTypes);
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, bool constructing,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args);
MCall *makeCallHelper(HandleFunction target, uint32_t argc, bool constructing,
bool cloneAtCallsite);
MCall *makeCallHelper(HandleFunction target, uint32_t argc, bool constructing);
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,
types::StackTypeSet *types, types::StackTypeSet *barrier);
bool makeCallBarrier(HandleFunction target, bool constructing,
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, uint32_t argc, bool constructing);
bool makeCall(HandleFunction target, bool constructing,
MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args);
inline bool TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types,
@ -453,7 +448,7 @@ class IonBuilder : public MIRGenerator
MGetPropertyCache *checkInlineableGetPropertyCache(uint32_t argc);
MPolyInlineDispatch *
makePolyInlineDispatch(JSContext *cx, int argc,
makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
MGetPropertyCache *getPropCache,
types::StackTypeSet *types, types::StackTypeSet *barrier,
MBasicBlock *bottom,

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

@ -2090,72 +2090,3 @@ js::ion::GetNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
return true;
}
bool
IonCacheCallsiteClone::attach(JSContext *cx, IonScript *ion, HandleFunction original,
HandleFunction clone)
{
MacroAssembler masm;
// Guard against object identity on the original.
RepatchLabel exit;
CodeOffsetJump exitOffset = masm.branchPtrWithPatch(Assembler::NotEqual, calleeReg(),
ImmWord(uintptr_t(original.get())), &exit);
masm.bind(&exit);
// Load the clone.
masm.movePtr(ImmWord(uintptr_t(clone.get())), outputReg());
RepatchLabel rejoin;
CodeOffsetJump rejoinOffset = masm.jumpWithPatch(&rejoin);
masm.bind(&rejoin);
Linker linker(masm);
IonCode *code = linker.newCode(cx);
if (!code)
return false;
rejoinOffset.fixup(&masm);
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump exitJump(code, exitOffset);
CodeLocationJump lastJump_ = lastJump();
PatchJump(lastJump_, CodeLocationLabel(code));
PatchJump(rejoinJump, rejoinLabel());
PatchJump(exitJump, cacheLabel());
updateLastJump(exitJump);
IonSpew(IonSpew_InlineCaches, "Generated CALL callee clone stub at %p", code->raw());
return true;
}
JSObject *
js::ion::CallsiteCloneCache(JSContext *cx, size_t cacheIndex, HandleObject callee)
{
AutoFlushCache afc ("CallsiteCloneCache");
// Act as the identity for functions that are not clone-at-callsite, as we
// generate this cache as long as some callees are clone-at-callsite.
RootedFunction fun(cx, callee->toFunction());
if (!fun->isCloneAtCallsite())
return fun;
IonScript *ion = GetTopIonJSScript(cx)->ionScript();
IonCacheCallsiteClone &cache = ion->getCache(cacheIndex).toCallsiteClone();
RootedFunction clone(cx, CloneFunctionAtCallsite(cx, fun, cache.callScript(), cache.callPc()));
if (!clone)
return NULL;
if (cache.stubCount() < MAX_STUBS) {
if (!cache.attach(cx, ion, fun, clone))
return NULL;
cache.incrementStubCount();
}
return clone;
}

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

@ -23,7 +23,6 @@ class IonCacheSetProperty;
class IonCacheGetElement;
class IonCacheBindName;
class IonCacheName;
class IonCacheCallsiteClone;
// Common structure encoding the state of a polymorphic inline cache contained
// in the code for an IonScript. IonCaches are used for polymorphic operations
@ -88,8 +87,7 @@ class IonCache
GetElement,
BindName,
Name,
NameTypeOf,
CallsiteClone
NameTypeOf
};
protected:
@ -140,12 +138,6 @@ class IonCache
PropertyName *name;
TypedOrValueRegisterSpace output;
} name;
struct {
Register callee;
Register output;
JSScript *callScript;
jsbytecode *callPc;
} callsiteclone;
} u;
// Registers live after the cache, excluding output registers. The initial
@ -237,10 +229,6 @@ class IonCache
JS_ASSERT(kind_ == Name || kind_ == NameTypeOf);
return *(IonCacheName *)this;
}
IonCacheCallsiteClone &toCallsiteClone() {
JS_ASSERT(kind_ == CallsiteClone);
return *(IonCacheCallsiteClone *)this;
}
void setScriptedLocation(UnrootedScript script, jsbytecode *pc) {
JS_ASSERT(!idempotent_);
@ -435,39 +423,6 @@ class IonCacheName : public IonCache
HandleShape shape);
};
class IonCacheCallsiteClone : public IonCache
{
public:
IonCacheCallsiteClone(CodeOffsetJump initialJump,
CodeOffsetLabel rejoinLabel,
CodeOffsetLabel cacheLabel,
RegisterSet liveRegs,
Register callee, JSScript *callScript, jsbytecode *callPc,
Register output)
{
init(CallsiteClone, liveRegs, initialJump, rejoinLabel, cacheLabel);
u.callsiteclone.callee = callee;
u.callsiteclone.callScript = callScript;
u.callsiteclone.callPc = callPc;
u.callsiteclone.output = output;
}
Register calleeReg() const {
return u.callsiteclone.callee;
}
HandleScript callScript() const {
return HandleScript::fromMarkedLocation(&u.callsiteclone.callScript);
}
jsbytecode *callPc() const {
return u.callsiteclone.callPc;
}
Register outputReg() const {
return u.callsiteclone.output;
}
bool attach(JSContext *cx, IonScript *ion, HandleFunction original, HandleFunction clone);
};
bool
GetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, MutableHandleValue vp);
@ -485,9 +440,6 @@ BindNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain);
bool
GetNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp);
JSObject *
CallsiteCloneCache(JSContext *cx, size_t cacheIndex, HandleObject callee);
} // namespace ion
} // namespace js

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

@ -2811,22 +2811,6 @@ class LCallGetIntrinsicValue : public LCallInstructionHelper<BOX_PIECES, 0, 0>
}
};
class LCallsiteCloneCache : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(CallsiteCloneCache);
LCallsiteCloneCache(const LAllocation &callee) {
setOperand(0, callee);
}
const LAllocation *callee() {
return getOperand(0);
}
const MCallsiteCloneCache *mir() const {
return mir_->toCallsiteCloneCache();
}
};
// Patchable jump to stubs generated for a GetProperty cache, which loads a
// boxed value.
class LGetPropertyCacheV : public LInstructionHelper<BOX_PIECES, 1, 0>

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

@ -154,7 +154,6 @@
_(CallGetProperty) \
_(GetNameCache) \
_(CallGetIntrinsicValue) \
_(CallsiteCloneCache) \
_(CallGetElement) \
_(CallSetElement) \
_(CallSetProperty) \

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

@ -1884,17 +1884,6 @@ LIRGenerator::visitCallGetIntrinsicValue(MCallGetIntrinsicValue *ins)
return assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitCallsiteCloneCache(MCallsiteCloneCache *ins)
{
JS_ASSERT(ins->callee()->type() == MIRType_Object);
LCallsiteCloneCache *lir = new LCallsiteCloneCache(useRegister(ins->callee()));
if (!define(lir, ins))
return false;
return assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitGetPropertyCache(MGetPropertyCache *ins)
{

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

@ -175,7 +175,6 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitDeleteProperty(MDeleteProperty *ins);
bool visitGetNameCache(MGetNameCache *ins);
bool visitCallGetIntrinsicValue(MCallGetIntrinsicValue *ins);
bool visitCallsiteCloneCache(MCallsiteCloneCache *ins);
bool visitCallGetElement(MCallGetElement *ins);
bool visitCallSetElement(MCallSetElement *ins);
bool visitSetPropertyCache(MSetPropertyCache *ins);

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

@ -395,11 +395,10 @@ MParameter::congruentTo(MDefinition * const &ins) const
}
MCall *
MCall::New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct,
types::StackTypeSet *calleeTypes)
MCall::New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct)
{
JS_ASSERT(maxArgc >= numActualArgs);
MCall *ins = new MCall(target, numActualArgs, construct, calleeTypes);
MCall *ins = new MCall(target, numActualArgs, construct);
if (!ins->init(maxArgc + NumNonArgumentOperands))
return NULL;
return ins;

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

@ -1171,23 +1171,18 @@ class MCall
CompilerRootFunction target_;
// Original value of argc from the bytecode.
uint32_t numActualArgs_;
// The typeset of the callee, could be NULL.
types::StackTypeSet *calleeTypes_;
MCall(JSFunction *target, uint32_t numActualArgs, bool construct,
types::StackTypeSet *calleeTypes)
MCall(JSFunction *target, uint32_t numActualArgs, bool construct)
: construct_(construct),
target_(target),
numActualArgs_(numActualArgs),
calleeTypes_(calleeTypes)
numActualArgs_(numActualArgs)
{
setResultType(MIRType_Value);
}
public:
INSTRUCTION_HEADER(Call)
static MCall *New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct,
types::StackTypeSet *calleeTypes);
static MCall *New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct);
void initPrepareCall(MDefinition *start) {
JS_ASSERT(start->isPrepareCall());
@ -1219,9 +1214,6 @@ class MCall
bool isConstructing() const {
return construct_;
}
types::StackTypeSet *calleeTypes() const {
return calleeTypes_;
}
// The number of stack arguments is the max between the number of formal
// arguments and the number of actual arguments. The number of stack
@ -4351,16 +4343,12 @@ class InlinePropertyTable : public TempObject
return entries_[i]->func;
}
void trimToAndMaybePatchTargets(AutoObjectVector &targets, AutoObjectVector &originals) {
void trimToTargets(AutoObjectVector &targets) {
size_t i = 0;
while (i < numEntries()) {
bool foundFunc = false;
// Compare using originals, but if we find a matching function,
// patch it to the target, which might be a clone.
for (size_t j = 0; j < originals.length(); j++) {
if (entries_[i]->func == originals[j]) {
if (entries_[i]->func != targets[j])
entries_[i] = new Entry(entries_[i]->typeObj, targets[j]->toFunction());
for (size_t j = 0; j < targets.length(); j++) {
if (entries_[i]->func == targets[j]) {
foundFunc = true;
break;
}
@ -4988,41 +4976,6 @@ class MCallGetIntrinsicValue : public MNullaryInstruction
}
};
class MCallsiteCloneCache
: public MUnaryInstruction,
public SingleObjectPolicy
{
jsbytecode *callPc_;
MCallsiteCloneCache(MDefinition *callee, jsbytecode *callPc)
: MUnaryInstruction(callee),
callPc_(callPc)
{
setResultType(MIRType_Object);
}
public:
INSTRUCTION_HEADER(CallsiteCloneCache);
static MCallsiteCloneCache *New(MDefinition *callee, jsbytecode *callPc) {
return new MCallsiteCloneCache(callee, callPc);
}
TypePolicy *typePolicy() {
return this;
}
MDefinition *callee() const {
return getOperand(0);
}
jsbytecode *callPc() const {
return callPc_;
}
// Callsite cloning is idempotent.
AliasSet getAliasSet() const {
return AliasSet::None();
}
};
class MSetPropertyInstruction : public MBinaryInstruction
{
CompilerRootPropertyName name_;

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

@ -123,7 +123,6 @@ namespace ion {
_(CallGetProperty) \
_(GetNameCache) \
_(CallGetIntrinsicValue) \
_(CallsiteCloneCache) \
_(CallGetElement) \
_(CallSetElement) \
_(CallSetProperty) \

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

@ -47,27 +47,15 @@ ShouldMonitorReturnType(JSFunction *fun)
}
bool
InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, Value *rval)
InvokeFunction(JSContext *cx, HandleFunction fun, uint32_t argc, Value *argv, Value *rval)
{
AssertCanGC();
RootedFunction fun(cx, fun0);
// In order to prevent massive bouncing between Ion and JM, see if we keep
// hitting functions that are uncompilable.
if (fun->isInterpreted()) {
if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
return false;
if (fun->isCloneAtCallsite()) {
RootedScript script(cx);
jsbytecode *pc;
types::TypeScript::GetPcScript(cx, &script, &pc);
fun = CloneFunctionAtCallsite(cx, fun0, script, pc);
if (!fun)
return false;
}
if (!fun->nonLazyScript()->canIonCompile()) {
UnrootedScript script = GetTopIonJSScript(cx);
if (script->hasIonScript() &&

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

@ -410,7 +410,7 @@ class AutoDetectInvalidation
}
};
bool InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, Value *rval);
bool InvokeFunction(JSContext *cx, HandleFunction fun, uint32_t argc, Value *argv, Value *rval);
JSObject *NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize);
bool CheckOverRecursed(JSContext *cx);

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

@ -242,58 +242,6 @@ JSRuntime::createJaegerRuntime(JSContext *cx)
}
#endif
void
JSCompartment::sweepCallsiteClones()
{
if (callsiteClones.initialized()) {
for (CallsiteCloneTable::Enum e(callsiteClones); !e.empty(); e.popFront()) {
CallsiteCloneKey key = e.front().key;
JSFunction *fun = e.front().value;
if (!key.script->isMarked() || !fun->isMarked())
e.removeFront();
}
}
}
RawFunction
js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
{
JS_ASSERT(cx->typeInferenceEnabled());
JS_ASSERT(fun->isCloneAtCallsite());
JS_ASSERT(types::UseNewTypeForClone(fun));
JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
typedef CallsiteCloneKey Key;
typedef CallsiteCloneTable Table;
Table &table = cx->compartment->callsiteClones;
if (!table.initialized() && !table.init())
return NULL;
Key key;
key.script = script;
key.offset = pc - script->code;
key.original = fun;
Table::AddPtr p = table.lookupForAdd(key);
if (p)
return p->value;
RootedObject parent(cx, fun->environment());
RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent,
JSFunction::ExtendedFinalizeKind));
if (!clone)
return NULL;
// Store a link back to the original for function.caller.
clone->setExtendedSlot(0, ObjectValue(*fun));
if (!table.add(p, key, clone.get()))
return NULL;
return clone;
}
JSContext *
js::NewContext(JSRuntime *rt, size_t stackChunkSize)
{

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

@ -58,39 +58,6 @@ namespace js {
typedef HashSet<JSObject *> ObjectSet;
struct CallsiteCloneKey {
/* The original function that we are cloning. */
JSFunction *original;
/* The script of the call. */
JSScript *script;
/* The offset of the call. */
uint32_t offset;
CallsiteCloneKey() { PodZero(this); }
typedef CallsiteCloneKey Lookup;
static inline uint32_t hash(CallsiteCloneKey key) {
return uint32_t(size_t(key.script->code + key.offset) ^ size_t(key.original));
}
static inline bool match(const CallsiteCloneKey &a, const CallsiteCloneKey &b) {
return a.script == b.script && a.offset == b.offset && a.original == b.original;
}
};
typedef HashMap<CallsiteCloneKey,
ReadBarriered<JSFunction>,
CallsiteCloneKey,
SystemAllocPolicy> CallsiteCloneTable;
RawFunction CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
HandleScript script, jsbytecode *pc);
typedef HashSet<JSObject *> ObjectSet;
/* Detects cycles when traversing an object graph. */
class AutoCycleDetector
{

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

@ -650,7 +650,6 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
sweepNewTypeObjectTable(newTypeObjects);
sweepNewTypeObjectTable(lazyTypeObjects);
sweepBreakpoints(fop);
sweepCallsiteClones();
if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet()))
global_ = NULL;

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

@ -349,14 +349,6 @@ struct JSCompartment : private JS::shadow::Compartment, public js::gc::GraphNode
js::types::TypeObject *getLazyType(JSContext *cx, js::Handle<js::TaggedProto> proto);
/*
* Hash table of all manually call site-cloned functions from within
* self-hosted code. Cloning according to call site provides extra
* sensitivity for type specialization and inlining.
*/
js::CallsiteCloneTable callsiteClones;
void sweepCallsiteClones();
/*
* Keeps track of the total number of malloc bytes connected to a
* compartment's GC things. This counter should be used in preference to

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

@ -84,13 +84,6 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
}
RootedFunction fun(cx, obj->toFunction());
/*
* Callsite clones should never escape to script, so get the original
* function.
*/
if (fun->isCallsiteClone())
fun = fun->getExtendedSlot(0).toObject().toFunction();
/*
* Mark the function's script as uninlineable, to expand any of its
* frames on the stack before we go looking for them. This allows the
@ -1521,8 +1514,29 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
* (JS_CloneFunctionObject) which dynamically ensures that 'script' has
* no enclosing lexical scope (only the global scope).
*/
if (clone->isInterpreted() && !CloneFunctionScript(cx, fun, clone))
return NULL;
if (clone->isInterpreted()) {
RootedScript script(cx, clone->nonLazyScript());
JS_ASSERT(script->compartment() == fun->compartment());
JS_ASSERT_IF(script->compartment() != cx->compartment,
!script->enclosingStaticScope());
RootedObject scope(cx, script->enclosingStaticScope());
clone->mutableScript().init(NULL);
RootedScript cscript(cx, CloneScript(cx, scope, clone, script));
if (!cscript)
return NULL;
clone->setScript(cscript);
cscript->setFunction(clone);
GlobalObject *global = script->compileAndGo ? &script->global() : NULL;
script = clone->nonLazyScript();
CallNewScriptHook(cx, script, clone);
Debugger::onNewScript(cx, script, global);
}
}
return clone;
}

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

@ -44,13 +44,6 @@ class JSFunction : public JSObject
HAS_DEFAULTS = 0x0800, /* function has at least one default parameter */
INTERPRETED_LAZY = 0x1000, /* function is interpreted but doesn't have a script yet */
/*
* Function is cloned anew at each callsite. This is temporarily
* needed for ParallelArray selfhosted code until type information can
* be made context sensitive. See discussion in bug 826148.
*/
CALLSITE_CLONE = 0x2000,
/* Derived Flags values for convenience: */
NATIVE_FUN = 0,
INTERPRETED_LAMBDA = INTERPRETED | LAMBDA
@ -107,11 +100,6 @@ class JSFunction : public JSObject
bool hasRest() const { return flags & HAS_REST; }
bool hasDefaults() const { return flags & HAS_DEFAULTS; }
/* Original functions that should be cloned are not extended. */
bool isCloneAtCallsite() const { return (flags & CALLSITE_CLONE) && !isExtended(); }
/* Cloned functions keep a backlink to the original in extended slot 0. */
bool isCallsiteClone() const { return (flags & CALLSITE_CLONE) && isExtended(); }
/* Compound attributes: */
bool isBuiltin() const {
return isNative() || isSelfHostedBuiltin();
@ -153,10 +141,6 @@ class JSFunction : public JSObject
flags |= SELF_HOSTED_CTOR;
}
void setIsCloneAtCallsite() {
flags |= CALLSITE_CLONE;
}
void setIsFunctionPrototype() {
JS_ASSERT(!isFunctionPrototype());
flags |= IS_FUN_PROTO;

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

@ -689,7 +689,6 @@ class TypeConstraintCall : public TypeConstraint
const char *kind() { return "call"; }
void newType(JSContext *cx, TypeSet *source, Type type);
bool newCallee(JSContext *cx, HandleFunction callee, HandleScript script);
};
void
@ -773,7 +772,6 @@ class TypeConstraintPropagateThis : public TypeConstraint
const char *kind() { return "propagatethis"; }
void newType(JSContext *cx, TypeSet *source, Type type);
bool newCallee(JSContext *cx, HandleFunction callee);
};
void
@ -1258,23 +1256,6 @@ TypeConstraintSetElement::newType(JSContext *cx, TypeSet *source, Type type)
}
}
static inline RawFunction
CloneCallee(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
{
/*
* Clone called functions at appropriate callsites to match interpreter
* behavior.
*/
RawFunction callee = CloneFunctionAtCallsite(cx, fun, script, pc);
if (!callee)
return NULL;
InferSpew(ISpewOps, "callsiteCloneType: #%u:%05u: %s",
script->id(), pc - script->code, TypeString(Type::ObjectType(callee)));
return callee;
}
void
TypeConstraintCall::newType(JSContext *cx, TypeSet *source, Type type)
{
@ -1367,30 +1348,11 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, Type type)
return;
}
if (callee->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, callee))
RootedScript calleeScript(cx, JSFunction::getOrCreateScript(cx, callee));
if (!calleeScript)
return;
/*
* As callsite cloning is a hint, we must propagate to both the original
* and the clone.
*/
if (callee->isCloneAtCallsite()) {
RootedFunction clone(cx, CloneCallee(cx, callee, script, pc));
if (!clone)
return;
if (!newCallee(cx, clone, script))
return;
}
newCallee(cx, callee, script);
}
bool
TypeConstraintCall::newCallee(JSContext *cx, HandleFunction callee, HandleScript script)
{
RootedScript calleeScript(cx, callee->nonLazyScript());
if (!calleeScript->ensureHasTypes(cx))
return false;
return;
unsigned nargs = callee->nargs;
@ -1398,7 +1360,7 @@ TypeConstraintCall::newCallee(JSContext *cx, HandleFunction callee, HandleScript
for (unsigned i = 0; i < callsite->argumentCount && i < nargs; i++) {
StackTypeSet *argTypes = callsite->argumentTypes[i];
StackTypeSet *types = TypeScript::ArgTypes(calleeScript, i);
argTypes->addSubsetBarrier(cx, script, callsite->pc, types);
argTypes->addSubsetBarrier(cx, script, pc, types);
}
/* Add void type for any formals in the callee not supplied at the call site. */
@ -1430,8 +1392,6 @@ TypeConstraintCall::newCallee(JSContext *cx, HandleFunction callee, HandleScript
*/
returnTypes->addSubset(cx, callsite->returnTypes);
}
return true;
}
void
@ -1439,7 +1399,6 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type)
{
AssertCanGC();
RootedScript script(cx, script_);
if (type.isUnknown() || type.isAnyObject()) {
/*
* The callee is unknown, make sure the call is monitored so we pick up
@ -1447,6 +1406,7 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type)
* CALLPROP, for other calls we are past the type barrier and a
* TypeConstraintCall will also monitor the call.
*/
RootedScript script(cx, script_);
cx->compartment->types.monitorBytecode(cx, script, callpc - script->code);
return;
}
@ -1469,37 +1429,14 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type)
return;
}
if (callee->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, callee))
if (!(JSFunction::getOrCreateScript(cx, callee) && callee->nonLazyScript()->ensureHasTypes(cx)))
return;
/*
* As callsite cloning is a hint, we must propagate to both the original
* and the clone.
*/
if (callee->isCloneAtCallsite()) {
RootedFunction clone(cx, CloneCallee(cx, callee, script, callpc));
if (!clone)
return;
if (!newCallee(cx, clone))
return;
}
newCallee(cx, callee);
}
bool
TypeConstraintPropagateThis::newCallee(JSContext *cx, HandleFunction callee)
{
if (!callee->nonLazyScript()->ensureHasTypes(cx))
return false;
TypeSet *thisTypes = TypeScript::ThisTypes(callee->nonLazyScript());
if (this->types)
this->types->addSubset(cx, thisTypes);
else
thisTypes->addType(cx, this->type);
return true;
}
void

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

@ -2359,25 +2359,8 @@ BEGIN_CASE(JSOP_FUNCALL)
bool construct = (*regs.pc == JSOP_NEW);
RootedFunction &fun = rootFunction0;
bool isFunction = IsFunctionObject(args.calleev(), fun.address());
/*
* Some builtins are marked as clone-at-callsite to increase precision of
* TI and JITs.
*/
if (isFunction) {
if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
goto error;
if (cx->typeInferenceEnabled() && fun->isCloneAtCallsite()) {
fun = CloneFunctionAtCallsite(cx, fun, script, regs.pc);
if (!fun)
goto error;
args.setCallee(ObjectValue(*fun));
}
}
/* Don't bother trying to fast-path calls to scripted non-constructors. */
if (!isFunction || !fun->isInterpretedConstructor()) {
if (!IsFunctionObject(args.calleev(), fun.address()) || !fun->isInterpretedConstructor()) {
if (construct) {
if (!InvokeConstructorKernel(cx, args))
goto error;
@ -2397,7 +2380,9 @@ BEGIN_CASE(JSOP_FUNCALL)
InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
RootedScript funScript(cx, fun->nonLazyScript());
RootedScript funScript(cx, JSFunction::getOrCreateScript(cx, fun));
if (!funScript)
goto error;
if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial))
goto error;

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

@ -2343,37 +2343,6 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
return dst;
}
bool
js::CloneFunctionScript(JSContext *cx, HandleFunction original, HandleFunction clone)
{
JS_ASSERT(clone->isInterpreted());
RootedScript script(cx, clone->nonLazyScript());
JS_ASSERT(script);
JS_ASSERT(script->compartment() == original->compartment());
JS_ASSERT_IF(script->compartment() != cx->compartment,
!script->enclosingStaticScope());
RootedObject scope(cx, script->enclosingStaticScope());
clone->mutableScript().init(NULL);
RawScript cscript = CloneScript(cx, scope, clone, script);
if (!cscript)
return false;
clone->setScript(cscript);
cscript->setFunction(clone);
GlobalObject *global = script->compileAndGo ? &script->global() : NULL;
script = clone->nonLazyScript();
CallNewScriptHook(cx, script, clone);
Debugger::onNewScript(cx, script, global);
return true;
}
DebugScript *
JSScript::debugScript()
{

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

@ -1300,9 +1300,6 @@ CurrentScriptFileLineOrigin(JSContext *cx, unsigned *linenop, LineOption = NOT_C
extern UnrootedScript
CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script);
bool
CloneFunctionScript(JSContext *cx, HandleFunction original, HandleFunction clone);
/*
* NB: after a successful XDR_DECODE, XDRScript callers must do any required
* subsequent set-up of owning function or script object and then call

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

@ -1637,7 +1637,6 @@ mjit::Compiler::finishThisUp()
chunk->nCallICs = callICs.length();
cursor += sizeof(ic::CallICInfo) * chunk->nCallICs;
for (size_t i = 0; i < chunk->nCallICs; i++) {
jitCallICs[i].funGuardLabel = fullCode.locationOf(callICs[i].funGuardLabel);
jitCallICs[i].funGuard = fullCode.locationOf(callICs[i].funGuard);
jitCallICs[i].funJump = fullCode.locationOf(callICs[i].funJump);
jitCallICs[i].slowPathStart = stubCode.locationOf(callICs[i].slowPathStart);
@ -4431,7 +4430,6 @@ mjit::Compiler::inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &call
* callee is scripted, compiled/compilable, and argc == nargs, then this
* guard is patched, and the compiled code address is baked in.
*/
callIC.funGuardLabel = masm.label();
Jump j = masm.branchPtrWithPatch(Assembler::NotEqual, icCalleeData, callIC.funGuard);
callIC.funJump = j;
@ -4631,11 +4629,6 @@ mjit::Compiler::inlineScriptedFunction(uint32_t argc, bool callingNew)
for (unsigned i = 0; i < ssa.numFrames(); i++) {
if (ssa.iterFrame(i).parent == a->inlineIndex && ssa.iterFrame(i).parentpc == PC) {
JSScript *script_ = ssa.iterFrame(i).script;
/* Don't inline if any of the callees should be cloned at callsite. */
if (script_->function()->isCloneAtCallsite())
return Compile_InlineAbort;
inlineCallees.append(script_);
if (script_->analysis()->numReturnSites() > 1)
calleeMultipleReturns = true;

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

@ -120,7 +120,6 @@ class Compiler : public BaseCompiler
* more comments.
*/
uint32_t callIndex;
Label funGuardLabel;
DataLabelPtr funGuard;
Jump funJump;
Jump hotJump;

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

@ -130,22 +130,6 @@ FindExceptionHandler(JSContext *cx)
* Clean up a frame and return.
*/
static inline bool
MaybeCloneAndPatchCallee(JSContext *cx, CallArgs args, HandleScript script, jsbytecode *pc)
{
if (cx->typeInferenceEnabled() &&
args.callee().isFunction() && args.callee().toFunction()->isCloneAtCallsite())
{
RootedFunction fun(cx, args.callee().toFunction());
fun = CloneFunctionAtCallsite(cx, fun, script, pc);
if (!fun)
return false;
args.setCallee(ObjectValue(*fun));
}
return true;
}
void JS_FASTCALL
stubs::SlowCall(VMFrame &f, uint32_t argc)
{
@ -153,13 +137,10 @@ stubs::SlowCall(VMFrame &f, uint32_t argc)
THROW();
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
RootedScript fscript(f.cx, f.script());
if (!MaybeCloneAndPatchCallee(f.cx, args, fscript, f.pc()))
THROW();
if (!InvokeKernel(f.cx, args))
THROW();
RootedScript fscript(f.cx, f.script());
types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
}
@ -167,13 +148,10 @@ void JS_FASTCALL
stubs::SlowNew(VMFrame &f, uint32_t argc)
{
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
RootedScript fscript(f.cx, f.script());
if (!MaybeCloneAndPatchCallee(f.cx, args, fscript, f.pc()))
THROW();
if (!InvokeConstructorKernel(f.cx, args))
THROW();
RootedScript fscript(f.cx, f.script());
types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
}
@ -232,10 +210,6 @@ stubs::FixupArity(VMFrame &f, uint32_t nactual)
/* Reserve enough space for a callee frame. */
CallArgs args = CallArgsFromSp(nactual, f.regs.sp);
if (fun->isCallsiteClone()) {
JS_ASSERT(args.callee().toFunction() == fun->getExtendedSlot(0).toObject().toFunction());
args.setCallee(ObjectValue(*fun));
}
StackFrame *fp = cx->stack.getFixupFrame(cx, DONT_REPORT_ERROR, args, fun,
script, ncode, initial, &f.stackLimit);
@ -313,7 +287,7 @@ UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
RootedFunction newfun(cx, args.callee().toFunction());
RootedScript newscript(cx, newfun->nonLazyScript());
RootedScript newscript(cx, JSFunction::getOrCreateScript(cx, newfun));
if (!newscript)
return false;
@ -421,18 +395,15 @@ stubs::UncachedNewHelper(VMFrame &f, uint32_t argc, UncachedCallResult &ucr)
ucr.init();
JSContext *cx = f.cx;
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
RootedScript fscript(cx, f.script());
if (!ucr.setFunction(cx, args, fscript, f.pc()))
THROW();
/* Try to do a fast inline call before the general Invoke path. */
if (ucr.fun && ucr.fun->isInterpretedConstructor()) {
if (IsFunctionObject(args.calleev(), ucr.fun.address()) && ucr.fun->isInterpretedConstructor()) {
if (!UncachedInlineCall(f, INITIAL_CONSTRUCT, &ucr.codeAddr, &ucr.unjittable, argc))
THROW();
} else {
if (!InvokeConstructorKernel(cx, args))
THROW();
RootedScript fscript(cx, f.script());
types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
}
}
@ -482,12 +453,8 @@ stubs::UncachedCallHelper(VMFrame &f, uint32_t argc, bool lowered, UncachedCallR
JSContext *cx = f.cx;
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
RootedScript fscript(cx, f.script());
if (!ucr.setFunction(cx, args, fscript, f.pc()))
THROW();
if (ucr.fun) {
if (IsFunctionObject(args.calleev(), ucr.fun.address())) {
if (ucr.fun->isInterpreted()) {
InitialFrameFlags initial = lowered ? INITIAL_LOWERED : INITIAL_NONE;
if (!UncachedInlineCall(f, initial, &ucr.codeAddr, &ucr.unjittable, argc))
@ -507,6 +474,7 @@ stubs::UncachedCallHelper(VMFrame &f, uint32_t argc, bool lowered, UncachedCallR
if (!InvokeKernel(f.cx, args))
THROW();
RootedScript fscript(cx, f.script());
types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
return;
}

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

@ -1029,13 +1029,13 @@ class CallCompiler : public BaseCompiler
linker.link(claspGuard, ic.slowPathStart);
linker.link(funGuard, ic.slowPathStart);
linker.link(done, ic.funGuard.labelAtOffset(ic.hotPathOffset));
ic.funJumpTarget = linker.finalize(f);
JSC::CodeLocationLabel cs = linker.finalize(f);
JaegerSpew(JSpew_PICs, "generated CALL closure stub %p (%lu bytes)\n",
ic.funJumpTarget.executableAddress(), (unsigned long) masm.size());
cs.executableAddress(), (unsigned long) masm.size());
Repatcher repatch(f.chunk());
repatch.relink(ic.funJump, ic.funJumpTarget);
repatch.relink(ic.funJump, cs);
return true;
}
@ -1209,67 +1209,10 @@ class CallCompiler : public BaseCompiler
ic.fastGuardedNative = fun;
linker.link(funGuard, ic.slowPathStart);
ic.funJumpTarget = linker.finalize(f);
JaegerSpew(JSpew_PICs, "generated native CALL stub %p (%lu bytes)\n",
ic.funJumpTarget.executableAddress(), (unsigned long) masm.size());
Repatcher repatch(f.chunk());
repatch.relink(ic.funJump, ic.funJumpTarget);
return true;
}
bool generateCallsiteCloneStub(HandleFunction original, HandleFunction fun)
{
AutoAssertNoGC nogc;
Assembler masm;
// If we have a callsite clone, we do the folowing hack:
//
// 1) Patch funJump to a stub which guards on the identity of the
// original function. If this guard fails, we jump to the original
// funJump target.
// 2) Load the clone into the callee register.
// 3) Jump *back* to funGuard.
//
// For the inline path, hopefully we will succeed upon jumping back to
// funGuard after loading the clone.
//
// This hack is not ideal, as we can actually fail the first funGuard
// twice: we fail the first funGuard, pass the second funGuard, load
// the clone, and jump back to the first funGuard. We fail the first
// funGuard again, and this time we also fail the second funGuard,
// since a function's clone is never equal to itself. Finally, we jump
// to the original funJump target.
// Guard on the original function's identity.
Jump originalGuard = masm.branchPtr(Assembler::NotEqual, ic.funObjReg, ImmPtr(original));
// Load the clone.
masm.move(ImmPtr(fun), ic.funObjReg);
// Jump back to the first fun guard.
Jump done = masm.jump();
LinkerHelper linker(masm, JSC::JAEGER_CODE);
JSC::ExecutablePool *ep = linker.init(f.cx);
if (!ep)
return false;
if (!linker.verifyRange(f.chunk())) {
disable();
return true;
}
linker.link(originalGuard, !!ic.funJumpTarget ? ic.funJumpTarget : ic.slowPathStart);
linker.link(done, ic.funGuardLabel);
JSC::CodeLocationLabel start = linker.finalize(f);
JaegerSpew(JSpew_PICs, "generated CALL clone stub %p (%lu bytes)\n",
JaegerSpew(JSpew_PICs, "generated native CALL stub %p (%lu bytes)\n",
start.executableAddress(), (unsigned long) masm.size());
JaegerSpew(JSpew_PICs, "guarding %p with clone %p\n", original.get(), fun.get());
Repatcher repatch(f.chunk());
repatch.relink(ic.funJump, start);
@ -1360,9 +1303,6 @@ class CallCompiler : public BaseCompiler
}
}
if (ucr.original && !generateCallsiteCloneStub(ucr.original, ucr.fun))
THROWV(NULL);
return ucr.codeAddr;
}
};

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

@ -165,9 +165,6 @@ struct CallICInfo {
FrameSize frameSize;
/* Label to the function object identity guard. */
JSC::CodeLocationLabel funGuardLabel;
/* Function object identity guard. */
JSC::CodeLocationDataLabelPtr funGuard;
@ -177,12 +174,6 @@ struct CallICInfo {
/* Inline to OOL jump, redirected by stubs. */
JSC::CodeLocationJump funJump;
/*
* Target of the above jump, remembered so that if we need to generate a
* callsite clone stub we can redirect to the original funJump target.
*/
JSC::CodeLocationLabel funJumpTarget;
/*
* If an Ion stub has been generated, its guard may be linked to another
* stub. The guard location is stored in this label.

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

@ -29,27 +29,6 @@ ReportAtomNotDefined(JSContext *cx, JSAtom *atom)
js_ReportIsNotDefined(cx, printable.ptr());
}
inline bool
stubs::UncachedCallResult::setFunction(JSContext *cx, CallArgs &args,
HandleScript callScript, jsbytecode *callPc)
{
if (!IsFunctionObject(args.calleev(), fun.address()))
return true;
if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
return false;
if (cx->typeInferenceEnabled() && fun->isCloneAtCallsite()) {
original = fun;
fun = CloneFunctionAtCallsite(cx, original, callScript, callPc);
if (!fun)
return false;
args.setCallee(ObjectValue(*fun));
}
return true;
}
} /* namespace mjit */
} /* namespace js */

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

@ -8,7 +8,6 @@
#if !defined jslogic_h__ && defined JS_METHODJIT
#define jslogic_h__
#include "jsfuninlines.h"
#include "MethodJIT.h"
namespace js {
@ -59,21 +58,16 @@ void JS_FASTCALL ScriptProbeOnlyEpilogue(VMFrame &f);
*/
struct UncachedCallResult {
RootedFunction fun; // callee function
RootedFunction original; // NULL if fun is not a callsite clone, else
// points to the original function.
void *codeAddr; // code address of compiled callee function
bool unjittable; // did we try to JIT and fail?
UncachedCallResult(JSContext *cx) : fun(cx), original(cx) {}
UncachedCallResult(JSContext *cx) : fun(cx) {}
void init() {
fun = NULL;
original = NULL;
codeAddr = NULL;
unjittable = false;
}
inline bool setFunction(JSContext *cx, CallArgs &args,
HandleScript callScript, jsbytecode *callPc);
};
/*