Bug 904759 - IonMonkey: Remove unused functions/MIR/LIR related to PolyInlineDispatch, r=djvj

This commit is contained in:
Hannes Verschore 2013-08-20 23:10:23 +02:00
parent 676384bb4e
commit 58a524e5b2
11 changed files with 0 additions and 357 deletions

View File

@ -593,45 +593,6 @@ CodeGenerator::visitTypeObjectDispatch(LTypeObjectDispatch *lir)
return true; return true;
} }
bool
CodeGenerator::visitPolyInlineDispatch(LPolyInlineDispatch *lir)
{
MPolyInlineDispatch *mir = lir->mir();
Register inputReg = ToRegister(lir->input());
InlinePropertyTable *inlinePropTable = mir->propTable();
if (inlinePropTable) {
// Temporary register is only assigned in the TypeObject case.
Register tempReg = ToRegister(lir->temp());
masm.loadPtr(Address(inputReg, JSObject::offsetOfType()), tempReg);
// Detect functions by TypeObject.
for (size_t i = 0; i < inlinePropTable->numEntries(); i++) {
types::TypeObject *typeObj = inlinePropTable->getTypeObject(i);
JSFunction *func = inlinePropTable->getFunction(i);
LBlock *target = mir->getFunctionBlock(func)->lir();
masm.branchPtr(Assembler::Equal, tempReg, ImmGCPtr(typeObj), target->label());
}
// Unknown function: jump to fallback block.
LBlock *fallback = mir->fallbackPrepBlock()->lir();
masm.jump(fallback->label());
return true;
}
// Compare function pointers directly.
for (size_t i = 0; i < mir->numCallees() - 1; i++) {
JSFunction *func = mir->getFunction(i);
LBlock *target = mir->getFunctionBlock(i)->lir();
masm.branchPtr(Assembler::Equal, inputReg, ImmGCPtr(func), target->label());
}
// There's no fallback case, so a final guard isn't necessary.
LBlock *target = mir->getFunctionBlock(mir->numCallees() - 1)->lir();
masm.jump(target->label());
return true;
}
typedef JSFlatString *(*IntToStringFn)(ThreadSafeContext *, int); typedef JSFlatString *(*IntToStringFn)(ThreadSafeContext *, int);
typedef ParallelResult (*IntToStringParFn)(ForkJoinSlice *, int, MutableHandleString); typedef ParallelResult (*IntToStringParFn)(ForkJoinSlice *, int, MutableHandleString);
static const VMFunctionsModal IntToStringInfo = VMFunctionsModal( static const VMFunctionsModal IntToStringInfo = VMFunctionsModal(

View File

@ -77,7 +77,6 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitTestVAndBranch(LTestVAndBranch *lir); bool visitTestVAndBranch(LTestVAndBranch *lir);
bool visitFunctionDispatch(LFunctionDispatch *lir); bool visitFunctionDispatch(LFunctionDispatch *lir);
bool visitTypeObjectDispatch(LTypeObjectDispatch *lir); bool visitTypeObjectDispatch(LTypeObjectDispatch *lir);
bool visitPolyInlineDispatch(LPolyInlineDispatch *lir);
bool visitIntToString(LIntToString *lir); bool visitIntToString(LIntToString *lir);
bool visitDoubleToString(LDoubleToString *lir); bool visitDoubleToString(LDoubleToString *lir);
bool visitInteger(LInteger *lir); bool visitInteger(LInteger *lir);

View File

@ -3984,121 +3984,6 @@ IonBuilder::getInlineableGetPropertyCache(CallInfo &callInfo)
return NULL; return NULL;
} }
MPolyInlineDispatch *
IonBuilder::makePolyInlineDispatch(JSContext *cx, CallInfo &callInfo,
MGetPropertyCache *getPropCache, MBasicBlock *bottom,
Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns)
{
// If we're not optimizing away a GetPropertyCache, then this is pretty simple.
if (!getPropCache)
return MPolyInlineDispatch::New(callInfo.fun());
InlinePropertyTable *inlinePropTable = getPropCache->propTable();
// Take a resumepoint at this point so we can capture the state of the stack
// immediately prior to the call operation.
MResumePoint *preCallResumePoint =
MResumePoint::New(current, pc, callerResumePoint_, MResumePoint::ResumeAt);
if (!preCallResumePoint)
return NULL;
DebugOnly<size_t> preCallFuncDefnIdx = preCallResumePoint->numOperands() - (((size_t) callInfo.argc()) + 2);
JS_ASSERT(preCallResumePoint->getOperand(preCallFuncDefnIdx) == callInfo.fun());
MDefinition *targetObject = getPropCache->object();
// If we got here, then we know the following:
// 1. The input to the CALL is a GetPropertyCache, or a GetPropertyCache
// followed by a TypeBarrier followed by an Unbox.
// 2. The GetPropertyCache has inlineable cases by guarding on the Object's type
// 3. The GetPropertyCache (and sequence of definitions) leading to the function
// definition is not used by anyone else.
// 4. Notably, this means that no resume points as of yet capture the GetPropertyCache,
// which implies that everything from the GetPropertyCache up to the call is
// repeatable.
// If we are optimizing away a getPropCache, we replace the funcDefn
// with a constant undefined on the stack.
int funcDefnDepth = -((int) callInfo.argc() + 2);
MConstant *undef = MConstant::New(UndefinedValue());
current->add(undef);
current->rewriteAtDepth(funcDefnDepth, undef);
// Now construct a fallbackPrepBlock that prepares the stack state for fallback.
// Namely it pops off all the arguments and the callee.
MBasicBlock *fallbackPrepBlock = newBlock(current, pc);
if (!fallbackPrepBlock)
return NULL;
// Pop formals (|fun|, |this| and arguments).
callInfo.popFormals(fallbackPrepBlock);
// Generate a fallback block that'll do the call, but the PC for this fallback block
// is the PC for the GetPropCache.
JS_ASSERT(inlinePropTable->pc() != NULL);
JS_ASSERT(inlinePropTable->priorResumePoint() != NULL);
MBasicBlock *fallbackBlock = newBlock(fallbackPrepBlock, inlinePropTable->pc(),
inlinePropTable->priorResumePoint());
if (!fallbackBlock)
return NULL;
fallbackPrepBlock->end(MGoto::New(fallbackBlock));
// The fallbackBlock inherits the state of the stack right before the getprop, which
// means we have to pop off the target of the getprop before performing it.
DebugOnly<MDefinition *> checkTargetObject = fallbackBlock->pop();
JS_ASSERT(checkTargetObject == targetObject);
// Remove the instructions leading to the function definition from the current
// block and add them to the fallback block. Also, discard the old instructions.
if (callInfo.fun()->isGetPropertyCache()) {
JS_ASSERT(callInfo.fun()->toGetPropertyCache() == getPropCache);
fallbackBlock->addFromElsewhere(getPropCache);
fallbackBlock->push(getPropCache);
} else {
JS_ASSERT(callInfo.fun()->isUnbox());
MUnbox *unbox = callInfo.fun()->toUnbox();
JS_ASSERT(unbox->input()->isTypeBarrier());
JS_ASSERT(unbox->type() == MIRType_Object);
JS_ASSERT(unbox->mode() == MUnbox::Infallible);
MTypeBarrier *typeBarrier = unbox->input()->toTypeBarrier();
JS_ASSERT(typeBarrier->input()->isGetPropertyCache());
JS_ASSERT(typeBarrier->input()->toGetPropertyCache() == getPropCache);
fallbackBlock->addFromElsewhere(getPropCache);
fallbackBlock->addFromElsewhere(typeBarrier);
fallbackBlock->addFromElsewhere(unbox);
fallbackBlock->push(unbox);
}
// Finally create a fallbackEnd block to do the actual call. The fallbackEnd block will
// have the |pc| restored to the current PC.
MBasicBlock *fallbackEndBlock = newBlock(fallbackBlock, pc, preCallResumePoint);
if (!fallbackEndBlock)
return NULL;
fallbackBlock->end(MGoto::New(fallbackEndBlock));
MBasicBlock *top = current;
setCurrentAndSpecializePhis(fallbackEndBlock);
// Make the actual call.
CallInfo realCallInfo(cx, callInfo.constructing());
if (!realCallInfo.init(callInfo))
return NULL;
realCallInfo.popFormals(current);
realCallInfo.wrapArgs(current);
RootedFunction target(cx, NULL);
makeCall(target, realCallInfo, false);
setCurrentAndSpecializePhis(top);
// Create a new MPolyInlineDispatch containing the getprop and the fallback block
return MPolyInlineDispatch::New(targetObject, inlinePropTable,
fallbackPrepBlock, fallbackBlock,
fallbackEndBlock);
}
IonBuilder::InliningStatus IonBuilder::InliningStatus
IonBuilder::inlineSingleCall(CallInfo &callInfo, JSFunction *target) IonBuilder::inlineSingleCall(CallInfo &callInfo, JSFunction *target)
{ {

View File

@ -592,11 +592,6 @@ class IonBuilder : public MIRGenerator
MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo); MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
MPolyInlineDispatch *
makePolyInlineDispatch(JSContext *cx, CallInfo &callInfo,
MGetPropertyCache *getPropCache, MBasicBlock *bottom,
Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns);
types::StackTypeSet *cloneTypeSet(types::StackTypeSet *types); types::StackTypeSet *cloneTypeSet(types::StackTypeSet *types);
// Use one of the below methods for updating the current block, rather than // Use one of the below methods for updating the current block, rather than

View File

@ -1448,26 +1448,6 @@ class LTypeObjectDispatch : public LInstructionHelper<0, 1, 1>
} }
}; };
class LPolyInlineDispatch : public LInstructionHelper<0, 1, 1>
{
// Accesses function/block table from MIR instruction.
public:
LIR_HEADER(PolyInlineDispatch)
LPolyInlineDispatch(const LAllocation &in, const LDefinition &temp) {
setOperand(0, in);
setTemp(0, temp);
}
const LDefinition *temp() {
return getTemp(0);
}
MPolyInlineDispatch *mir() {
return mir_->toPolyInlineDispatch();
}
};
// Compares two integral values of the same JS type, either integer or object. // Compares two integral values of the same JS type, either integer or object.
// For objects, both operands are in registers. // For objects, both operands are in registers.
class LCompare : public LInstructionHelper<1, 2, 0> class LCompare : public LInstructionHelper<1, 2, 0>

View File

@ -72,7 +72,6 @@
_(TestOAndBranch) \ _(TestOAndBranch) \
_(FunctionDispatch) \ _(FunctionDispatch) \
_(TypeObjectDispatch) \ _(TypeObjectDispatch) \
_(PolyInlineDispatch) \
_(Compare) \ _(Compare) \
_(CompareAndBranch) \ _(CompareAndBranch) \
_(CompareD) \ _(CompareD) \

View File

@ -753,16 +753,6 @@ LIRGenerator::visitTypeObjectDispatch(MTypeObjectDispatch *ins)
return add(lir, ins); return add(lir, ins);
} }
bool
LIRGenerator::visitPolyInlineDispatch(MPolyInlineDispatch *ins)
{
LDefinition tempDef = LDefinition::BogusTemp();
if (ins->propTable())
tempDef = temp();
LPolyInlineDispatch *lir = new LPolyInlineDispatch(useRegister(ins->input()), tempDef);
return add(lir, ins);
}
static inline bool static inline bool
CanEmitCompareAtUses(MInstruction *ins) CanEmitCompareAtUses(MInstruction *ins)
{ {

View File

@ -119,7 +119,6 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitTest(MTest *test); bool visitTest(MTest *test);
bool visitFunctionDispatch(MFunctionDispatch *ins); bool visitFunctionDispatch(MFunctionDispatch *ins);
bool visitTypeObjectDispatch(MTypeObjectDispatch *ins); bool visitTypeObjectDispatch(MTypeObjectDispatch *ins);
bool visitPolyInlineDispatch(MPolyInlineDispatch *ins);
bool visitCompare(MCompare *comp); bool visitCompare(MCompare *comp);
bool visitTypeOf(MTypeOf *ins); bool visitTypeOf(MTypeOf *ins);
bool visitToId(MToId *ins); bool visitToId(MToId *ins);

View File

@ -6004,169 +6004,6 @@ class MFunctionDispatch : public MDispatchInstruction
} }
}; };
// Represents a polymorphic dispatch to one or more functions.
class MPolyInlineDispatch MOZ_FINAL : public MControlInstruction, public SingleObjectPolicy
{
// A table to map JSFunctions to the blocks that execute them.
struct Entry {
MConstant *funcConst;
MBasicBlock *block;
Entry(MConstant *funcConst, MBasicBlock *block)
: funcConst(funcConst), block(block) {}
};
Vector<Entry, 4, IonAllocPolicy> dispatchTable_;
MUse operand_;
InlinePropertyTable *inlinePropertyTable_;
MBasicBlock *fallbackPrepBlock_;
MBasicBlock *fallbackMidBlock_;
MBasicBlock *fallbackEndBlock_;
MPolyInlineDispatch(MDefinition *ins)
: dispatchTable_(),
inlinePropertyTable_(NULL),
fallbackPrepBlock_(NULL),
fallbackMidBlock_(NULL),
fallbackEndBlock_(NULL)
{
setOperand(0, ins);
}
MPolyInlineDispatch(MDefinition *ins, InlinePropertyTable *inlinePropertyTable,
MBasicBlock *fallbackPrepBlock,
MBasicBlock *fallbackMidBlock,
MBasicBlock *fallbackEndBlock)
: dispatchTable_(),
inlinePropertyTable_(inlinePropertyTable),
fallbackPrepBlock_(fallbackPrepBlock),
fallbackMidBlock_(fallbackMidBlock),
fallbackEndBlock_(fallbackEndBlock)
{
setOperand(0, ins);
}
protected:
virtual void setOperand(size_t index, MDefinition *operand) {
JS_ASSERT(index == 0);
operand_.set(operand, this, index);
operand->addUse(&operand_);
}
MUse *getUseFor(size_t index) {
JS_ASSERT(index == 0);
return &operand_;
}
void setSuccessor(size_t i, MBasicBlock *successor) {
JS_ASSERT(i < numSuccessors());
if (inlinePropertyTable_ && (i == numSuccessors() - 1))
fallbackPrepBlock_ = successor;
else
dispatchTable_[i].block = successor;
}
public:
INSTRUCTION_HEADER(PolyInlineDispatch)
virtual MDefinition *getOperand(size_t index) const {
JS_ASSERT(index == 0);
return operand_.producer();
}
virtual size_t numOperands() const {
return 1;
}
virtual size_t numSuccessors() const {
return dispatchTable_.length() + (inlinePropertyTable_ ? 1 : 0);
}
virtual void replaceSuccessor(size_t i, MBasicBlock *successor) {
setSuccessor(i, successor);
}
MBasicBlock *getSuccessor(size_t i) const {
JS_ASSERT(i < numSuccessors());
if (inlinePropertyTable_ && (i == numSuccessors() - 1))
return fallbackPrepBlock_;
else
return dispatchTable_[i].block;
}
static MPolyInlineDispatch *New(MDefinition *ins) {
return new MPolyInlineDispatch(ins);
}
static MPolyInlineDispatch *New(MDefinition *ins, InlinePropertyTable *inlinePropTable,
MBasicBlock *fallbackPrepBlock,
MBasicBlock *fallbackMidBlock,
MBasicBlock *fallbackEndBlock)
{
return new MPolyInlineDispatch(ins, inlinePropTable,
fallbackPrepBlock,
fallbackMidBlock,
fallbackEndBlock);
}
size_t numCallees() const {
return dispatchTable_.length();
}
void addCallee(MConstant *funcConst, MBasicBlock *block) {
dispatchTable_.append(Entry(funcConst, block));
}
MConstant *getFunctionConstant(size_t i) const {
JS_ASSERT(i < numCallees());
return dispatchTable_[i].funcConst;
}
JSFunction *getFunction(size_t i) const {
return &getFunctionConstant(i)->value().toObject().as<JSFunction>();
}
MBasicBlock *getFunctionBlock(size_t i) const {
JS_ASSERT(i < numCallees());
return dispatchTable_[i].block;
}
MBasicBlock *getFunctionBlock(JSFunction *func) const {
for (size_t i = 0; i < numCallees(); i++) {
if (getFunction(i) == func)
return getFunctionBlock(i);
}
MOZ_ASSUME_UNREACHABLE("Bad function lookup!");
}
InlinePropertyTable *propTable() const {
return inlinePropertyTable_;
}
MBasicBlock *fallbackPrepBlock() const {
JS_ASSERT(inlinePropertyTable_ != NULL);
return fallbackPrepBlock_;
}
MBasicBlock *fallbackMidBlock() const {
JS_ASSERT(inlinePropertyTable_ != NULL);
return fallbackMidBlock_;
}
MBasicBlock *fallbackEndBlock() const {
JS_ASSERT(inlinePropertyTable_ != NULL);
return fallbackEndBlock_;
}
MDefinition *input() const {
return getOperand(0);
}
TypePolicy *typePolicy() {
return this;
}
};
class MGetElementCache class MGetElementCache
: public MBinaryInstruction : public MBinaryInstruction
{ {

View File

@ -19,7 +19,6 @@ namespace ion {
_(Test) \ _(Test) \
_(TypeObjectDispatch) \ _(TypeObjectDispatch) \
_(FunctionDispatch) \ _(FunctionDispatch) \
_(PolyInlineDispatch) \
_(Compare) \ _(Compare) \
_(Phi) \ _(Phi) \
_(Beta) \ _(Beta) \

View File

@ -270,7 +270,6 @@ class ParallelSafetyVisitor : public MInstructionVisitor
SAFE_OP(GuardThreadLocalObject) SAFE_OP(GuardThreadLocalObject)
SAFE_OP(CheckInterruptPar) SAFE_OP(CheckInterruptPar)
SAFE_OP(CheckOverRecursedPar) SAFE_OP(CheckOverRecursedPar)
SAFE_OP(PolyInlineDispatch)
SAFE_OP(FunctionDispatch) SAFE_OP(FunctionDispatch)
SAFE_OP(TypeObjectDispatch) SAFE_OP(TypeObjectDispatch)
SAFE_OP(IsCallable) SAFE_OP(IsCallable)