зеркало из https://github.com/mozilla/gecko-dev.git
Bug 915763 - Remove TypeScript::dynamicList and dynamic Monitor functions. r=bhackett
This commit is contained in:
Родитель
ea76441a45
Коммит
d3c054db17
|
@ -152,7 +152,6 @@ struct TypeInferenceSizes
|
|||
{
|
||||
#define FOR_EACH_SIZE(macro) \
|
||||
macro(js::NotLiveGCThing, typeScripts) \
|
||||
macro(js::NotLiveGCThing, typeResults) \
|
||||
macro(js::NotLiveGCThing, pendingArrays) \
|
||||
macro(js::NotLiveGCThing, allocationSiteTables) \
|
||||
macro(js::NotLiveGCThing, arrayTypeTables) \
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
eval('(function () {\
|
||||
function range(n) {\
|
||||
for (var i = 0; i < 100000; i++)\
|
||||
for (var i = 0; i < 5000; i++)\
|
||||
yield i;\
|
||||
}\
|
||||
var r = range(10);\
|
||||
var i = 0;\
|
||||
for (var x in r)\
|
||||
assertEq(x,i++);\
|
||||
' + '})();');
|
||||
' + '})();');
|
||||
|
|
|
@ -1375,22 +1375,15 @@ HandleShapeGuardFailure(JSContext *cx, HandleScript outerScript, HandleScript in
|
|||
}
|
||||
|
||||
static bool
|
||||
HandleCachedShapeGuardFailure(JSContext *cx, HandleScript outerScript, HandleScript innerScript)
|
||||
HandleBaselineInfoBailout(JSContext *cx, JSScript *outerScript, JSScript *innerScript)
|
||||
{
|
||||
IonSpew(IonSpew_Bailouts, "Cached shape guard failure %s:%d, inlined into %s:%d",
|
||||
IonSpew(IonSpew_Bailouts, "Baseline info failure %s:%d, inlined into %s:%d",
|
||||
innerScript->filename(), innerScript->lineno,
|
||||
outerScript->filename(), outerScript->lineno);
|
||||
|
||||
JS_ASSERT(!outerScript->ionScript()->invalidated());
|
||||
|
||||
outerScript->failedShapeGuard = true;
|
||||
|
||||
// No need to purge baseline ICs. Baseline will do one of two things: add a new
|
||||
// optimized stub (preventing monomorphic IC caching), or set a flag indicating that
|
||||
// an unoptimizable access was made, also preventing mono IC caching.
|
||||
|
||||
IonSpew(IonSpew_BaselineBailouts, "Invalidating due to cached shape guard failure");
|
||||
|
||||
IonSpew(IonSpew_BaselineBailouts, "Invalidating due to invalid baseline info");
|
||||
return Invalidate(cx, outerScript);
|
||||
}
|
||||
|
||||
|
@ -1487,11 +1480,7 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
|
|||
// Do nothing.
|
||||
break;
|
||||
case Bailout_ArgumentCheck:
|
||||
case Bailout_TypeBarrier:
|
||||
case Bailout_Monitor:
|
||||
// Reflow types. But in baseline, this will happen automatically because
|
||||
// for any monitored op (or for argument checks), bailout will resume into
|
||||
// the monitoring IC which will handle the type updates.
|
||||
// Do nothing, bailout will resume before the argument monitor ICs.
|
||||
break;
|
||||
case Bailout_BoundsCheck:
|
||||
if (!HandleBoundsCheckFailure(cx, outerScript, innerScript))
|
||||
|
@ -1501,8 +1490,8 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
|
|||
if (!HandleShapeGuardFailure(cx, outerScript, innerScript))
|
||||
return false;
|
||||
break;
|
||||
case Bailout_CachedShapeGuard:
|
||||
if (!HandleCachedShapeGuardFailure(cx, outerScript, innerScript))
|
||||
case Bailout_BaselineInfo:
|
||||
if (!HandleBaselineInfoBailout(cx, outerScript, innerScript))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -2461,23 +2461,23 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
|||
switch(op) {
|
||||
case JSOP_ADD:
|
||||
// Do an add.
|
||||
if (!AddValues(cx, script, pc, &lhsCopy, &rhsCopy, ret.address()))
|
||||
if (!AddValues(cx, &lhsCopy, &rhsCopy, ret.address()))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_SUB:
|
||||
if (!SubValues(cx, script, pc, &lhsCopy, &rhsCopy, ret.address()))
|
||||
if (!SubValues(cx, &lhsCopy, &rhsCopy, ret.address()))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_MUL:
|
||||
if (!MulValues(cx, script, pc, &lhsCopy, &rhsCopy, ret.address()))
|
||||
if (!MulValues(cx, &lhsCopy, &rhsCopy, ret.address()))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_DIV:
|
||||
if (!DivValues(cx, script, pc, &lhsCopy, &rhsCopy, ret.address()))
|
||||
if (!DivValues(cx, &lhsCopy, &rhsCopy, ret.address()))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_MOD:
|
||||
if (!ModValues(cx, script, pc, &lhsCopy, &rhsCopy, ret.address()))
|
||||
if (!ModValues(cx, &lhsCopy, &rhsCopy, ret.address()))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_BITOR: {
|
||||
|
@ -2516,7 +2516,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac
|
|||
break;
|
||||
}
|
||||
case JSOP_URSH: {
|
||||
if (!UrshOperation(cx, script, pc, lhs, rhs, ret.address()))
|
||||
if (!UrshOperation(cx, lhs, rhs, ret.address()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
@ -8691,6 +8691,9 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb
|
|||
if (!IteratorNext(cx, iteratorObject, res))
|
||||
return false;
|
||||
|
||||
if (!res.isString() && !stub->hasNonStringResult())
|
||||
stub->setHasNonStringResult();
|
||||
|
||||
if (iteratorObject->is<PropertyIteratorObject>() &&
|
||||
!stub->hasStub(ICStub::IteratorNext_Native))
|
||||
{
|
||||
|
|
|
@ -5614,6 +5614,14 @@ class ICIteratorNext_Fallback : public ICFallbackStub
|
|||
return space->allocate<ICIteratorNext_Fallback>(code);
|
||||
}
|
||||
|
||||
void setHasNonStringResult() {
|
||||
JS_ASSERT(extra_ == 0);
|
||||
extra_ = 1;
|
||||
}
|
||||
bool hasNonStringResult() const {
|
||||
return extra_;
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
|
|
|
@ -351,6 +351,20 @@ BaselineInspector::hasSeenAccessedGetter(jsbytecode *pc)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineInspector::hasSeenNonStringIterNext(jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(JSOp(*pc) == JSOP_ITERNEXT);
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
const ICEntry &entry = icEntryFromPC(pc);
|
||||
ICStub *stub = entry.fallbackStub();
|
||||
|
||||
return stub->toIteratorNext_Fallback()->hasNonStringResult();
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
|
||||
{
|
||||
|
|
|
@ -109,6 +109,7 @@ class BaselineInspector
|
|||
bool hasSeenNegativeIndexGetElement(jsbytecode *pc);
|
||||
bool hasSeenAccessedGetter(jsbytecode *pc);
|
||||
bool hasSeenDoubleResult(jsbytecode *pc);
|
||||
bool hasSeenNonStringIterNext(jsbytecode *pc);
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
|
|
|
@ -3865,10 +3865,8 @@ CodeGenerator::visitModD(LModD *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*BinaryFn)(JSContext *, HandleScript, jsbytecode *,
|
||||
MutableHandleValue, MutableHandleValue, Value *);
|
||||
typedef ParallelResult (*BinaryParFn)(ForkJoinSlice *, HandleValue, HandleValue,
|
||||
Value *);
|
||||
typedef bool (*BinaryFn)(JSContext *, MutableHandleValue, MutableHandleValue, Value *);
|
||||
typedef ParallelResult (*BinaryParFn)(ForkJoinSlice *, HandleValue, HandleValue, Value *);
|
||||
|
||||
static const VMFunction AddInfo = FunctionInfo<BinaryFn>(js::AddValues);
|
||||
static const VMFunction SubInfo = FunctionInfo<BinaryFn>(js::SubValues);
|
||||
|
@ -3884,10 +3882,6 @@ CodeGenerator::visitBinaryV(LBinaryV *lir)
|
|||
{
|
||||
pushArg(ToValue(lir, LBinaryV::RhsInput));
|
||||
pushArg(ToValue(lir, LBinaryV::LhsInput));
|
||||
if (gen->info().executionMode() == SequentialExecution) {
|
||||
pushArg(ImmPtr(lir->mirRaw()->toInstruction()->resumePoint()->pc()));
|
||||
pushArg(ImmGCPtr(current->mir()->info().script()));
|
||||
}
|
||||
|
||||
switch (lir->jsop()) {
|
||||
case JSOP_ADD:
|
||||
|
|
|
@ -3774,7 +3774,7 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
|||
{
|
||||
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
|
||||
if (!types->unknown()) {
|
||||
MTypeBarrier *barrier = MTypeBarrier::New(callInfo.thisArg(), cloneTypeSet(types), Bailout_Normal);
|
||||
MTypeBarrier *barrier = MTypeBarrier::New(callInfo.thisArg(), cloneTypeSet(types));
|
||||
current->add(barrier);
|
||||
callInfo.setThis(barrier);
|
||||
}
|
||||
|
@ -8535,7 +8535,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name, jsid id,
|
|||
spew("Inlining monomorphic GETPROP");
|
||||
|
||||
Shape *objShape = shapes[0];
|
||||
obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
|
||||
obj = addShapeGuard(obj, objShape, Bailout_ShapeGuard);
|
||||
|
||||
Shape *shape = objShape->search(cx, id);
|
||||
JS_ASSERT(shape);
|
||||
|
@ -8943,7 +8943,7 @@ IonBuilder::setPropTryInlineAccess(bool *emitted, MDefinition *obj,
|
|||
// that the shape is still a lastProperty, and calling Shape::search
|
||||
// on dictionary mode shapes that aren't lastProperty is invalid.
|
||||
Shape *objShape = shapes[0];
|
||||
obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
|
||||
obj = addShapeGuard(obj, objShape, Bailout_ShapeGuard);
|
||||
|
||||
Shape *shape = objShape->search(cx, NameToId(name));
|
||||
JS_ASSERT(shape);
|
||||
|
@ -9229,8 +9229,8 @@ IonBuilder::jsop_iternext()
|
|||
if (!resumeAfter(ins))
|
||||
return false;
|
||||
|
||||
if (!nonStringIteration_ && types::IterationValuesMustBeStrings(script())) {
|
||||
ins = MUnbox::New(ins, MIRType_String, MUnbox::Infallible);
|
||||
if (!nonStringIteration_ && !inspector->hasSeenNonStringIterNext(pc)) {
|
||||
ins = MUnbox::New(ins, MIRType_String, MUnbox::Fallible, Bailout_BaselineInfo);
|
||||
current->add(ins);
|
||||
current->rewriteAtDepth(-1, ins);
|
||||
}
|
||||
|
|
|
@ -31,21 +31,14 @@ enum BailoutKind
|
|||
// a type mismatch in the arguments that necessitates a reflow.
|
||||
Bailout_ArgumentCheck,
|
||||
|
||||
// A bailout required to monitor a newly observed type in a type inference
|
||||
// barrier.
|
||||
Bailout_TypeBarrier,
|
||||
|
||||
// A bailout required to monitor the result of a VM call.
|
||||
Bailout_Monitor,
|
||||
|
||||
// A bailout triggered by a bounds-check failure.
|
||||
Bailout_BoundsCheck,
|
||||
|
||||
// A shape guard based on TI information failed.
|
||||
Bailout_ShapeGuard,
|
||||
|
||||
// A shape guard based on JM ICs failed.
|
||||
Bailout_CachedShapeGuard
|
||||
// A bailout caused by invalid assumptions based on Baseline code.
|
||||
Bailout_BaselineInfo
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -57,16 +50,12 @@ BailoutKindString(BailoutKind kind)
|
|||
return "Bailout_Normal";
|
||||
case Bailout_ArgumentCheck:
|
||||
return "Bailout_ArgumentCheck";
|
||||
case Bailout_TypeBarrier:
|
||||
return "Bailout_TypeBarrier";
|
||||
case Bailout_Monitor:
|
||||
return "Bailout_Monitor";
|
||||
case Bailout_BoundsCheck:
|
||||
return "Bailout_BoundsCheck";
|
||||
case Bailout_ShapeGuard:
|
||||
return "Bailout_ShapeGuard";
|
||||
case Bailout_CachedShapeGuard:
|
||||
return "Bailout_CachedShapeGuard";
|
||||
case Bailout_BaselineInfo:
|
||||
return "Bailout_BaselineInfo";
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Invalid BailoutKind");
|
||||
}
|
||||
|
|
|
@ -1065,7 +1065,7 @@ LIRGenerator::lowerShiftOp(JSOp op, MShiftInstruction *ins)
|
|||
|
||||
LShiftI *lir = new LShiftI(op);
|
||||
if (op == JSOP_URSH) {
|
||||
if (ins->toUrsh()->fallible() && !assignSnapshot(lir))
|
||||
if (ins->toUrsh()->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
}
|
||||
return lowerForShift(lir, ins, lhs, rhs);
|
||||
|
@ -1267,7 +1267,7 @@ LIRGenerator::visitAdd(MAdd *ins)
|
|||
ReorderCommutative(&lhs, &rhs);
|
||||
LAddI *lir = new LAddI;
|
||||
|
||||
if (ins->fallible() && !assignSnapshot(lir))
|
||||
if (ins->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
|
||||
if (!lowerForALU(lir, ins, lhs, rhs))
|
||||
|
@ -1992,7 +1992,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
// (Emit LBail for visibility).
|
||||
if (ins->alwaysBails()) {
|
||||
LBail *bail = new LBail();
|
||||
if (!assignSnapshot(bail, ins->bailoutKind()))
|
||||
if (!assignSnapshot(bail))
|
||||
return false;
|
||||
return redefine(ins, ins->input()) && add(bail, ins);
|
||||
}
|
||||
|
@ -2003,7 +2003,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
LTypeBarrierV *barrier = new LTypeBarrierV(tmp);
|
||||
if (!useBox(barrier, LTypeBarrierV::Input, ins->input()))
|
||||
return false;
|
||||
if (!assignSnapshot(barrier, ins->bailoutKind()))
|
||||
if (!assignSnapshot(barrier))
|
||||
return false;
|
||||
return redefine(ins, ins->input()) && add(barrier, ins);
|
||||
}
|
||||
|
@ -2013,7 +2013,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
{
|
||||
LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
|
||||
LTypeBarrierO *barrier = new LTypeBarrierO(useRegister(ins->getOperand(0)), tmp);
|
||||
if (!assignSnapshot(barrier, ins->bailoutKind()))
|
||||
if (!assignSnapshot(barrier))
|
||||
return false;
|
||||
return redefine(ins, ins->getOperand(0)) && add(barrier, ins);
|
||||
}
|
||||
|
@ -2616,12 +2616,12 @@ LIRGenerator::visitGetPropertyPolymorphic(MGetPropertyPolymorphic *ins)
|
|||
|
||||
if (ins->type() == MIRType_Value) {
|
||||
LGetPropertyPolymorphicV *lir = new LGetPropertyPolymorphicV(useRegister(ins->obj()));
|
||||
return assignSnapshot(lir, Bailout_CachedShapeGuard) && defineBox(lir, ins);
|
||||
return assignSnapshot(lir, Bailout_ShapeGuard) && defineBox(lir, ins);
|
||||
}
|
||||
|
||||
LDefinition maybeTemp = (ins->type() == MIRType_Double) ? temp() : LDefinition::BogusTemp();
|
||||
LGetPropertyPolymorphicT *lir = new LGetPropertyPolymorphicT(useRegister(ins->obj()), maybeTemp);
|
||||
return assignSnapshot(lir, Bailout_CachedShapeGuard) && define(lir, ins);
|
||||
return assignSnapshot(lir, Bailout_ShapeGuard) && define(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2633,13 +2633,13 @@ LIRGenerator::visitSetPropertyPolymorphic(MSetPropertyPolymorphic *ins)
|
|||
LSetPropertyPolymorphicV *lir = new LSetPropertyPolymorphicV(useRegister(ins->obj()), temp());
|
||||
if (!useBox(lir, LSetPropertyPolymorphicV::Value, ins->value()))
|
||||
return false;
|
||||
return assignSnapshot(lir, Bailout_CachedShapeGuard) && add(lir, ins);
|
||||
return assignSnapshot(lir, Bailout_ShapeGuard) && add(lir, ins);
|
||||
}
|
||||
|
||||
LAllocation value = useRegisterOrConstant(ins->value());
|
||||
LSetPropertyPolymorphicT *lir =
|
||||
new LSetPropertyPolymorphicT(useRegister(ins->obj()), value, ins->value()->type(), temp());
|
||||
return assignSnapshot(lir, Bailout_CachedShapeGuard) && add(lir, ins);
|
||||
return assignSnapshot(lir, Bailout_ShapeGuard) && add(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -643,11 +643,9 @@ PrintBailoutKind(FILE *fp, BailoutKind bailoutKind)
|
|||
switch(bailoutKind) {
|
||||
case Bailout_Normal: fprintf(fp, "(normal)"); break;
|
||||
case Bailout_ArgumentCheck: fprintf(fp, "(args)"); break;
|
||||
case Bailout_TypeBarrier: fprintf(fp, "(typebarrier)"); break;
|
||||
case Bailout_Monitor: fprintf(fp, "(monitor)"); break;
|
||||
case Bailout_BoundsCheck: fprintf(fp, "(boundscheck)"); break;
|
||||
case Bailout_ShapeGuard: fprintf(fp, "(shapeguard)"); break;
|
||||
case Bailout_CachedShapeGuard: fprintf(fp, "(cached shapeguard)"); break;
|
||||
case Bailout_BaselineInfo: fprintf(fp, "(baseline info)"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -675,12 +673,6 @@ MUnbox::printOpcode(FILE *fp) const
|
|||
case TypeBarrier: fprintf(fp, " (typebarrier)"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (mode() == Infallible)
|
||||
return;
|
||||
|
||||
fprintf(fp, " ");
|
||||
PrintBailoutKind(fp, bailoutKind());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -689,10 +681,7 @@ MTypeBarrier::printOpcode(FILE *fp) const
|
|||
PrintOpcodeName(fp, op());
|
||||
fprintf(fp, " ");
|
||||
getOperand(0)->printName(fp);
|
||||
fprintf(fp, " ");
|
||||
|
||||
PrintBailoutKind(fp, bailoutKind());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MPhi::removeOperand(size_t index)
|
||||
|
|
|
@ -2270,10 +2270,7 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
|||
INSTRUCTION_HEADER(Unbox)
|
||||
static MUnbox *New(MDefinition *ins, MIRType type, Mode mode)
|
||||
{
|
||||
BailoutKind kind = Bailout_Normal;
|
||||
if (mode == TypeBarrier && ins->isEffectful())
|
||||
kind = Bailout_TypeBarrier;
|
||||
return new MUnbox(ins, type, mode, kind);
|
||||
return new MUnbox(ins, type, mode, Bailout_Normal);
|
||||
}
|
||||
|
||||
static MUnbox *New(MDefinition *ins, MIRType type, Mode mode, BailoutKind kind)
|
||||
|
@ -7921,9 +7918,7 @@ class MTypeBarrier
|
|||
: public MUnaryInstruction,
|
||||
public TypeBarrierPolicy
|
||||
{
|
||||
BailoutKind bailoutKind_;
|
||||
|
||||
MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types, BailoutKind bailoutKind)
|
||||
MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types)
|
||||
: MUnaryInstruction(def)
|
||||
{
|
||||
JS_ASSERT(!types->unknown());
|
||||
|
@ -7934,19 +7929,13 @@ class MTypeBarrier
|
|||
|
||||
setGuard();
|
||||
setMovable();
|
||||
bailoutKind_ = bailoutKind;
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(TypeBarrier)
|
||||
|
||||
static MTypeBarrier *New(MDefinition *def, types::TemporaryTypeSet *types) {
|
||||
BailoutKind kind = def->isEffectful() ? Bailout_TypeBarrier : Bailout_Normal;
|
||||
return new MTypeBarrier(def, types, kind);
|
||||
}
|
||||
static MTypeBarrier *New(MDefinition *def, types::TemporaryTypeSet *types,
|
||||
BailoutKind kind) {
|
||||
return new MTypeBarrier(def, types, kind);
|
||||
return new MTypeBarrier(def, types);
|
||||
}
|
||||
|
||||
void printOpcode(FILE *fp) const;
|
||||
|
@ -7958,9 +7947,6 @@ class MTypeBarrier
|
|||
bool congruentTo(MDefinition *def) const {
|
||||
return false;
|
||||
}
|
||||
BailoutKind bailoutKind() const {
|
||||
return bailoutKind_;
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
|
|
@ -278,8 +278,7 @@ TypeBarrierPolicy::adjustInputs(MInstruction *def)
|
|||
return true;
|
||||
}
|
||||
|
||||
MUnbox *unbox = MUnbox::New(ins->getOperand(0), outputType,
|
||||
MUnbox::TypeBarrier, ins->bailoutKind());
|
||||
MUnbox *unbox = MUnbox::New(ins->getOperand(0), outputType, MUnbox::TypeBarrier);
|
||||
ins->block()->insertBefore(ins, unbox);
|
||||
ins->replaceOperand(0, unbox);
|
||||
return true;
|
||||
|
|
|
@ -56,9 +56,8 @@ InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Val
|
|||
|
||||
// Clone function at call site if needed.
|
||||
if (fun->nonLazyScript()->shouldCloneAtCallsite) {
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
types::TypeScript::GetPcScript(cx, script.address(), &pc);
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
fun = CloneFunctionAtCallsite(cx, fun, script, pc);
|
||||
if (!fun)
|
||||
return false;
|
||||
|
@ -83,9 +82,8 @@ InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Val
|
|||
}
|
||||
|
||||
if (obj->is<JSFunction>()) {
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
types::TypeScript::GetPcScript(cx, script.address(), &pc);
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
types::TypeScript::Monitor(cx, script, pc, rv.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ LIRGeneratorARM::lowerDivI(MDiv *div)
|
|||
int32_t shift = FloorLog2(rhs);
|
||||
if (rhs > 0 && 1 << shift == rhs) {
|
||||
LDivPowTwoI *lir = new LDivPowTwoI(useRegisterAtStart(div->lhs()), shift);
|
||||
if (div->fallible() && !assignSnapshot(lir))
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, div);
|
||||
}
|
||||
|
@ -285,23 +285,23 @@ LIRGeneratorARM::lowerDivI(MDiv *div)
|
|||
|
||||
if (hasIDIV()) {
|
||||
LDivI *lir = new LDivI(useRegister(div->lhs()), useRegister(div->rhs()), temp());
|
||||
if (div->fallible() && !assignSnapshot(lir))
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, div);
|
||||
} else {
|
||||
LSoftDivI *lir = new LSoftDivI(useFixed(div->lhs(), r0), use(div->rhs(), r1),
|
||||
tempFixed(r2), tempFixed(r3));
|
||||
if (div->fallible() && !assignSnapshot(lir))
|
||||
return false;
|
||||
return defineFixed(lir, div, LAllocation(AnyRegister(r0)));
|
||||
}
|
||||
|
||||
LSoftDivI *lir = new LSoftDivI(useFixed(div->lhs(), r0), use(div->rhs(), r1),
|
||||
tempFixed(r2), tempFixed(r3));
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineFixed(lir, div, LAllocation(AnyRegister(r0)));
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGeneratorARM::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
|
||||
{
|
||||
LMulI *lir = new LMulI;
|
||||
if (mul->fallible() && !assignSnapshot(lir))
|
||||
if (mul->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return lowerForALU(lir, mul, lhs, rhs);
|
||||
}
|
||||
|
@ -317,12 +317,12 @@ LIRGeneratorARM::lowerModI(MMod *mod)
|
|||
int32_t shift = FloorLog2(rhs);
|
||||
if (rhs > 0 && 1 << shift == rhs) {
|
||||
LModPowTwoI *lir = new LModPowTwoI(useRegister(mod->lhs()), shift);
|
||||
if (mod->fallible() && !assignSnapshot(lir))
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, mod);
|
||||
} else if (shift < 31 && (1 << (shift+1)) - 1 == rhs) {
|
||||
LModMaskI *lir = new LModMaskI(useRegister(mod->lhs()), temp(LDefinition::GENERAL), shift+1);
|
||||
if (mod->fallible() && !assignSnapshot(lir))
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, mod);
|
||||
}
|
||||
|
@ -330,16 +330,16 @@ LIRGeneratorARM::lowerModI(MMod *mod)
|
|||
|
||||
if (hasIDIV()) {
|
||||
LModI *lir = new LModI(useRegister(mod->lhs()), useRegister(mod->rhs()), temp());
|
||||
if (mod->fallible() && !assignSnapshot(lir))
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, mod);
|
||||
} else {
|
||||
LSoftModI *lir = new LSoftModI(useFixed(mod->lhs(), r0), use(mod->rhs(), r1),
|
||||
tempFixed(r2), tempFixed(r3), temp(LDefinition::GENERAL));
|
||||
if (mod->fallible() && !assignSnapshot(lir))
|
||||
return false;
|
||||
return defineFixed(lir, mod, LAllocation(AnyRegister(r1)));
|
||||
}
|
||||
|
||||
LSoftModI *lir = new LSoftModI(useFixed(mod->lhs(), r0), use(mod->rhs(), r1),
|
||||
tempFixed(r2), tempFixed(r3), temp(LDefinition::GENERAL));
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineFixed(lir, mod, LAllocation(AnyRegister(r1)));
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -121,7 +121,7 @@ LIRGeneratorX86Shared::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
|
|||
// Note: lhs is used twice, so that we can restore the original value for the
|
||||
// negative zero check.
|
||||
LMulI *lir = new LMulI(useRegisterAtStart(lhs), useOrConstant(rhs), use(lhs));
|
||||
if (mul->fallible() && !assignSnapshot(lir))
|
||||
if (mul->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineReuseInput(lir, mul, 0);
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ LIRGeneratorX86Shared::lowerDivI(MDiv *div)
|
|||
int32_t shift = FloorLog2(rhs);
|
||||
if (rhs > 0 && 1 << shift == rhs) {
|
||||
LDivPowTwoI *lir = new LDivPowTwoI(useRegisterAtStart(div->lhs()), useRegister(div->lhs()), shift);
|
||||
if (div->fallible() && !assignSnapshot(lir))
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineReuseInput(lir, div, 0);
|
||||
}
|
||||
|
@ -163,13 +163,13 @@ LIRGeneratorX86Shared::lowerDivI(MDiv *div)
|
|||
return define(new LInteger(1), div);
|
||||
|
||||
LDivSelfI *lir = new LDivSelfI(useRegisterAtStart(div->lhs()));
|
||||
if (div->fallible() && !assignSnapshot(lir))
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, div);
|
||||
}
|
||||
|
||||
LDivI *lir = new LDivI(useFixed(div->lhs(), eax), useRegister(div->rhs()), tempFixed(edx));
|
||||
if (div->fallible() && !assignSnapshot(lir))
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineFixed(lir, div, LAllocation(AnyRegister(eax)));
|
||||
}
|
||||
|
@ -185,13 +185,13 @@ LIRGeneratorX86Shared::lowerModI(MMod *mod)
|
|||
int32_t shift = FloorLog2(rhs);
|
||||
if (rhs > 0 && 1 << shift == rhs) {
|
||||
LModPowTwoI *lir = new LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
|
||||
if (mod->fallible() && !assignSnapshot(lir))
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineReuseInput(lir, mod, 0);
|
||||
}
|
||||
}
|
||||
LModI *lir = new LModI(useRegister(mod->lhs()), useRegister(mod->rhs()), tempFixed(eax));
|
||||
if (mod->fallible() && !assignSnapshot(lir))
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
|
||||
}
|
||||
|
|
|
@ -2879,56 +2879,6 @@ CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, HandleFunction fu
|
|||
// Interface functions
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
types::MarkIteratorUnknownSlow(JSContext *cx)
|
||||
{
|
||||
/* Check whether we are actually at an ITER opcode. */
|
||||
|
||||
jsbytecode *pc;
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
if (!script || !pc)
|
||||
return;
|
||||
|
||||
if (JSOp(*pc) != JSOP_ITER)
|
||||
return;
|
||||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!script->ensureHasTypes(cx))
|
||||
return;
|
||||
|
||||
/*
|
||||
* This script is iterating over an actual Iterator or Generator object, or
|
||||
* an object with a custom __iterator__ hook. In such cases 'for in' loops
|
||||
* can produce values other than strings, and the types of the ITER opcodes
|
||||
* in the script need to be updated. During analysis this is done with the
|
||||
* forTypes in the analysis state, but we don't keep a pointer to this type
|
||||
* set and need to scan the script to fix affected opcodes.
|
||||
*/
|
||||
|
||||
TypeResult *result = script->types->dynamicList;
|
||||
while (result) {
|
||||
if (result->offset == UINT32_MAX) {
|
||||
/* Already know about custom iterators used in this script. */
|
||||
JS_ASSERT(result->type.isUnknown());
|
||||
return;
|
||||
}
|
||||
result = result->next;
|
||||
}
|
||||
|
||||
InferSpew(ISpewOps, "externalType: customIterator #%u", script->id());
|
||||
|
||||
result = cx->new_<TypeResult>(UINT32_MAX, Type::UnknownType());
|
||||
if (!result) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
result->next = script->types->dynamicList;
|
||||
script->types->dynamicList = result;
|
||||
|
||||
AddPendingRecompile(cx, script);
|
||||
}
|
||||
|
||||
void
|
||||
types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args,
|
||||
bool constructing)
|
||||
|
@ -2963,61 +2913,6 @@ IsAboutToBeFinalized(TypeObjectKey *key)
|
|||
return isAboutToBeFinalized;
|
||||
}
|
||||
|
||||
void
|
||||
types::TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, Type type)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
|
||||
if (!script->types)
|
||||
return;
|
||||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/* Directly update associated type sets for applicable bytecodes. */
|
||||
if (js_CodeSpec[*pc].format & JOF_TYPESET) {
|
||||
if (!script->ensureHasBytecodeTypeMap(cx)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
TypeSet *types = TypeScript::BytecodeTypes(script, pc);
|
||||
if (!types->hasType(type)) {
|
||||
InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
|
||||
script->id(), pc - script->code, TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Scan all intermediate types on the script to check for a dupe. */
|
||||
TypeResult *result, **pstart = &script->types->dynamicList, **presult = pstart;
|
||||
while (*presult) {
|
||||
result = *presult;
|
||||
if (result->offset == unsigned(pc - script->code) && result->type == type) {
|
||||
if (presult != pstart) {
|
||||
/* Move to the head of the list, maintain LRU order. */
|
||||
*presult = result->next;
|
||||
result->next = *pstart;
|
||||
*pstart = result;
|
||||
}
|
||||
return;
|
||||
}
|
||||
presult = &result->next;
|
||||
}
|
||||
|
||||
InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
|
||||
script->id(), pc - script->code, TypeString(type));
|
||||
|
||||
result = cx->new_<TypeResult>(pc - script->code, type);
|
||||
if (!result) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
result->next = script->types->dynamicList;
|
||||
script->types->dynamicList = result;
|
||||
|
||||
AddPendingRecompile(cx, script);
|
||||
}
|
||||
|
||||
void
|
||||
types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
{
|
||||
|
@ -3912,21 +3807,6 @@ TypeScript::Sweep(FreeOp *fop, JSScript *script)
|
|||
for (unsigned i = 0; i < num; i++)
|
||||
typeArray[i].sweep(compartment->zone());
|
||||
|
||||
TypeResult **presult = &script->types->dynamicList;
|
||||
while (*presult) {
|
||||
TypeResult *result = *presult;
|
||||
Type type = result->type;
|
||||
|
||||
if (!type.isUnknown() && !type.isAnyObject() && type.isObject() &&
|
||||
IsAboutToBeFinalized(type.objectKey()))
|
||||
{
|
||||
*presult = result->next;
|
||||
fop->delete_(result);
|
||||
} else {
|
||||
presult = &result->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Freeze constraints on stack type sets need to be regenerated the next
|
||||
* time the script is analyzed.
|
||||
|
@ -3937,12 +3817,6 @@ TypeScript::Sweep(FreeOp *fop, JSScript *script)
|
|||
void
|
||||
TypeScript::destroy()
|
||||
{
|
||||
while (dynamicList) {
|
||||
TypeResult *next = dynamicList->next;
|
||||
js_delete(dynamicList);
|
||||
dynamicList = next;
|
||||
}
|
||||
|
||||
js_free(this);
|
||||
}
|
||||
|
||||
|
@ -3995,12 +3869,6 @@ SizeOfScriptTypeInferenceData(JSScript *script, JS::TypeInferenceSizes *sizes,
|
|||
}
|
||||
|
||||
sizes->typeScripts += mallocSizeOf(typeScript);
|
||||
|
||||
TypeResult *result = typeScript->dynamicList;
|
||||
while (result) {
|
||||
sizes->typeResults += mallocSizeOf(result);
|
||||
result = result->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -718,23 +718,6 @@ void
|
|||
AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
|
||||
JSScript *script, JSScript *calleeScript);
|
||||
|
||||
/*
|
||||
* Handler which persists information about dynamic types pushed within a
|
||||
* script which can affect its behavior and are not covered by JOF_TYPESET ops,
|
||||
* such as integer operations which overflow to a double. These persist across
|
||||
* GCs, and are used to re-seed script types when they are reanalyzed.
|
||||
*/
|
||||
struct TypeResult
|
||||
{
|
||||
uint32_t offset;
|
||||
Type type;
|
||||
TypeResult *next;
|
||||
|
||||
TypeResult(uint32_t offset, Type type)
|
||||
: offset(offset), type(type), next(NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
/* Is this a reasonable PC to be doing inlining on? */
|
||||
inline bool isInlinableCall(jsbytecode *pc);
|
||||
|
||||
|
@ -1159,9 +1142,6 @@ class TypeScript
|
|||
uint32_t *bytecodeMap;
|
||||
|
||||
public:
|
||||
/* Dynamic types generated at points within this script. */
|
||||
TypeResult *dynamicList;
|
||||
|
||||
/*
|
||||
* Array of type sets storing the possible inputs to property reads.
|
||||
* Generated the first time the script is analyzed by inference and kept
|
||||
|
@ -1187,19 +1167,6 @@ class TypeScript
|
|||
static inline TypeObject *InitObject(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSProtoKey kind);
|
||||
|
||||
/*
|
||||
* Monitor a bytecode pushing a value which is not accounted for by the
|
||||
* inference type constraints, such as integer overflow.
|
||||
*/
|
||||
static inline void MonitorOverflow(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
static inline void MonitorString(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
static inline void MonitorUnknown(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
static inline void GetPcScript(JSContext *cx, JSScript **script, jsbytecode **pc);
|
||||
static inline void MonitorOverflow(JSContext *cx);
|
||||
static inline void MonitorString(JSContext *cx);
|
||||
static inline void MonitorUnknown(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Monitor a bytecode pushing any value. This must be called for any opcode
|
||||
* which is JOF_TYPESET, and where either the script has not been analyzed
|
||||
|
|
|
@ -500,17 +500,6 @@ GetTypeCallerInitObject(JSContext *cx, JSProtoKey key)
|
|||
|
||||
void MarkIteratorUnknownSlow(JSContext *cx);
|
||||
|
||||
/*
|
||||
* When using a custom iterator within the initialization of a 'for in' loop,
|
||||
* mark the iterator values as unknown.
|
||||
*/
|
||||
inline void
|
||||
MarkIteratorUnknown(JSContext *cx)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
MarkIteratorUnknownSlow(cx);
|
||||
}
|
||||
|
||||
void TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args,
|
||||
bool constructing);
|
||||
|
||||
|
@ -838,66 +827,11 @@ TypeScript::Monitor(JSContext *cx, JSScript *script, jsbytecode *pc, const js::V
|
|||
TypeMonitorResult(cx, script, pc, rval);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorOverflow(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
TypeDynamicResult(cx, script, pc, Type::DoubleType());
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorString(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
TypeDynamicResult(cx, script, pc, Type::StringType());
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorUnknown(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
TypeDynamicResult(cx, script, pc, Type::UnknownType());
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::GetPcScript(JSContext *cx, JSScript **script, jsbytecode **pc)
|
||||
{
|
||||
*script = cx->currentScript(pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorOverflow(JSContext *cx)
|
||||
{
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, script.address(), &pc);
|
||||
MonitorOverflow(cx, script, pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorString(JSContext *cx)
|
||||
{
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, script.address(), &pc);
|
||||
MonitorString(cx, script, pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorUnknown(JSContext *cx)
|
||||
{
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, script.address(), &pc);
|
||||
MonitorUnknown(cx, script, pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::Monitor(JSContext *cx, const js::Value &rval)
|
||||
{
|
||||
RootedScript script(cx);
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, script.address(), &pc);
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
Monitor(cx, script, pc, rval);
|
||||
}
|
||||
|
||||
|
@ -1578,20 +1512,6 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
|
|||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
IterationValuesMustBeStrings(JSScript *script)
|
||||
{
|
||||
// Return true if no custom non-string-producing iterators have been used
|
||||
// in a 'for in' loop within the script.
|
||||
types::TypeResult *result = script->types->dynamicList;
|
||||
while (result) {
|
||||
if (result->offset == UINT32_MAX)
|
||||
return false;
|
||||
result = result->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} } /* namespace js::types */
|
||||
|
||||
inline bool
|
||||
|
|
|
@ -604,7 +604,6 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa
|
|||
if (!iterobj)
|
||||
return false;
|
||||
vp.setObject(*iterobj);
|
||||
types::MarkIteratorUnknown(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -681,16 +680,13 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa
|
|||
}
|
||||
|
||||
miss:
|
||||
if (obj->is<ProxyObject>()) {
|
||||
types::MarkIteratorUnknown(cx);
|
||||
if (obj->is<ProxyObject>())
|
||||
return Proxy::iterate(cx, obj, flags, vp);
|
||||
}
|
||||
|
||||
if (!GetCustomIterator(cx, obj, flags, vp))
|
||||
return false;
|
||||
if (!vp.isUndefined()) {
|
||||
types::MarkIteratorUnknown(cx);
|
||||
if (!vp.isUndefined())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: for (var p in null) succeeds by iterating over no properties. */
|
||||
|
|
|
@ -2218,9 +2218,8 @@ js::CurrentScriptFileLineOrigin(JSContext *cx, const char **file, unsigned *line
|
|||
JSPrincipals **origin, LineOption opt)
|
||||
{
|
||||
if (opt == CALLED_FROM_JSOP_EVAL) {
|
||||
JSScript *script = NULL;
|
||||
jsbytecode *pc = NULL;
|
||||
types::TypeScript::GetPcScript(cx, &script, &pc);
|
||||
JSScript *script = cx->currentScript(&pc);
|
||||
JS_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_SPREADEVAL);
|
||||
JS_ASSERT(*(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
|
||||
: JSOP_SPREADEVAL_LENGTH)) == JSOP_LINENO);
|
||||
|
|
|
@ -312,15 +312,12 @@ NegOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue val
|
|||
*/
|
||||
int32_t i;
|
||||
if (val.isInt32() && (i = val.toInt32()) != 0 && i != INT32_MIN) {
|
||||
i = -i;
|
||||
res.setInt32(i);
|
||||
res.setInt32(-i);
|
||||
} else {
|
||||
double d;
|
||||
if (!ToNumber(cx, val, &d))
|
||||
return false;
|
||||
d = -d;
|
||||
if (!res.setNumber(d) && !val.isDouble())
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
res.setNumber(-d);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -344,8 +341,6 @@ ToIdOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue ob
|
|||
return false;
|
||||
|
||||
res.set(IdToValue(id));
|
||||
if (!res.isInt32())
|
||||
types::TypeScript::MonitorUnknown(cx, script, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -638,16 +633,14 @@ BitRsh(JSContext *cx, HandleValue lhs, HandleValue rhs, int *out)
|
|||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
UrshOperation(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
HandleValue lhs, HandleValue rhs, Value *out)
|
||||
UrshOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *out)
|
||||
{
|
||||
uint32_t left;
|
||||
int32_t right;
|
||||
if (!ToUint32(cx, lhs, &left) || !ToInt32(cx, rhs, &right))
|
||||
return false;
|
||||
left >>= right & 31;
|
||||
if (!out->setNumber(uint32_t(left)))
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
out->setNumber(uint32_t(left));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,8 +187,6 @@ js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval_, MutableHandle
|
|||
if (!JSObject::getProperty(cx, obj, obj, cx->names().noSuchMethod, &value))
|
||||
return false;
|
||||
|
||||
TypeScript::MonitorUnknown(cx);
|
||||
|
||||
if (value.isObject()) {
|
||||
JSObject *obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, nullptr, nullptr);
|
||||
if (!obj)
|
||||
|
@ -1074,27 +1072,20 @@ ComputeImplicitThis(JSContext *cx, HandleObject obj, MutableHandleValue vp)
|
|||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
AddOperation(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
AddOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
if (lhs.isInt32() && rhs.isInt32()) {
|
||||
int32_t l = lhs.toInt32(), r = rhs.toInt32();
|
||||
double d = double(l) + double(r);
|
||||
if (!res->setNumber(d))
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
res->setNumber(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If either operand is an object, any non-integer result must be
|
||||
* reported to inference.
|
||||
*/
|
||||
bool lIsObject = lhs.isObject(), rIsObject = rhs.isObject();
|
||||
|
||||
if (!ToPrimitive(cx, lhs))
|
||||
return false;
|
||||
if (!ToPrimitive(cx, rhs))
|
||||
return false;
|
||||
|
||||
bool lIsString, rIsString;
|
||||
if ((lIsString = lhs.isString()) | (rIsString = rhs.isString())) {
|
||||
JSString *lstr, *rstr;
|
||||
|
@ -1122,68 +1113,49 @@ AddOperation(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
if (!str)
|
||||
return false;
|
||||
}
|
||||
if (lIsObject || rIsObject)
|
||||
types::TypeScript::MonitorString(cx, script, pc);
|
||||
res->setString(str);
|
||||
} else {
|
||||
double l, r;
|
||||
if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r))
|
||||
return false;
|
||||
l += r;
|
||||
Value nres = NumberValue(l);
|
||||
if (nres.isDouble() &&
|
||||
(lIsObject || rIsObject || (!lhs.isDouble() && !rhs.isDouble()))) {
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
}
|
||||
*res = nres;
|
||||
res->setNumber(l + r);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
SubOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
|
||||
Value *res)
|
||||
SubOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
|
||||
{
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
double d = d1 - d2;
|
||||
if (!res->setNumber(d) && !(lhs.isDouble() || rhs.isDouble()))
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
res->setNumber(d1 - d2);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
MulOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
|
||||
Value *res)
|
||||
MulOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
|
||||
{
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
double d = d1 * d2;
|
||||
if (!res->setNumber(d) && !(lhs.isDouble() || rhs.isDouble()))
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
res->setNumber(d1 * d2);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
DivOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
|
||||
Value *res)
|
||||
DivOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
|
||||
{
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
res->setNumber(NumberDiv(d1, d2));
|
||||
|
||||
if (d2 == 0 || (res->isDouble() && !(lhs.isDouble() || rhs.isDouble())))
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ModOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs, HandleValue rhs,
|
||||
Value *res)
|
||||
ModOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res)
|
||||
{
|
||||
int32_t l, r;
|
||||
if (lhs.isInt32() && rhs.isInt32() &&
|
||||
|
@ -1198,7 +1170,6 @@ ModOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs
|
|||
return false;
|
||||
|
||||
res->setNumber(NumberMod(d1, d2));
|
||||
types::TypeScript::MonitorOverflow(cx, script, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2066,7 +2037,7 @@ BEGIN_CASE(JSOP_URSH)
|
|||
{
|
||||
HandleValue lval = regs.stackHandleAt(-2);
|
||||
HandleValue rval = regs.stackHandleAt(-1);
|
||||
if (!UrshOperation(cx, script, regs.pc, lval, rval, ®s.sp[-2]))
|
||||
if (!UrshOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -2076,7 +2047,7 @@ BEGIN_CASE(JSOP_ADD)
|
|||
{
|
||||
MutableHandleValue lval = regs.stackHandleAt(-2);
|
||||
MutableHandleValue rval = regs.stackHandleAt(-1);
|
||||
if (!AddOperation(cx, script, regs.pc, lval, rval, ®s.sp[-2]))
|
||||
if (!AddOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -2087,7 +2058,7 @@ BEGIN_CASE(JSOP_SUB)
|
|||
RootedValue &lval = rootValue0, &rval = rootValue1;
|
||||
lval = regs.sp[-2];
|
||||
rval = regs.sp[-1];
|
||||
if (!SubOperation(cx, script, regs.pc, lval, rval, ®s.sp[-2]))
|
||||
if (!SubOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -2098,7 +2069,7 @@ BEGIN_CASE(JSOP_MUL)
|
|||
RootedValue &lval = rootValue0, &rval = rootValue1;
|
||||
lval = regs.sp[-2];
|
||||
rval = regs.sp[-1];
|
||||
if (!MulOperation(cx, script, regs.pc, lval, rval, ®s.sp[-2]))
|
||||
if (!MulOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -2109,7 +2080,7 @@ BEGIN_CASE(JSOP_DIV)
|
|||
RootedValue &lval = rootValue0, &rval = rootValue1;
|
||||
lval = regs.sp[-2];
|
||||
rval = regs.sp[-1];
|
||||
if (!DivOperation(cx, script, regs.pc, lval, rval, ®s.sp[-2]))
|
||||
if (!DivOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -2120,7 +2091,7 @@ BEGIN_CASE(JSOP_MOD)
|
|||
RootedValue &lval = rootValue0, &rval = rootValue1;
|
||||
lval = regs.sp[-2];
|
||||
rval = regs.sp[-1];
|
||||
if (!ModOperation(cx, script, regs.pc, lval, rval, ®s.sp[-2]))
|
||||
if (!ModOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -2157,8 +2128,6 @@ END_CASE(JSOP_NEG)
|
|||
BEGIN_CASE(JSOP_POS)
|
||||
if (!ToNumber(cx, regs.stackHandleAt(-1)))
|
||||
goto error;
|
||||
if (!regs.sp[-1].isInt32())
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc);
|
||||
END_CASE(JSOP_POS)
|
||||
|
||||
BEGIN_CASE(JSOP_DELNAME)
|
||||
|
@ -3739,51 +3708,39 @@ js::InitElementArray(JSContext *cx, jsbytecode *pc, HandleObject obj, uint32_t i
|
|||
}
|
||||
|
||||
bool
|
||||
js::AddValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res)
|
||||
js::AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
return AddOperation(cx, script, pc, lhs, rhs, res);
|
||||
return AddOperation(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SubValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res)
|
||||
js::SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
return SubOperation(cx, script, pc, lhs, rhs, res);
|
||||
return SubOperation(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
bool
|
||||
js::MulValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res)
|
||||
js::MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
return MulOperation(cx, script, pc, lhs, rhs, res);
|
||||
return MulOperation(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DivValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res)
|
||||
js::DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
return DivOperation(cx, script, pc, lhs, rhs, res);
|
||||
return DivOperation(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
bool
|
||||
js::ModValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res)
|
||||
js::ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
return ModOperation(cx, script, pc, lhs, rhs, res);
|
||||
return ModOperation(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
bool
|
||||
js::UrshValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res)
|
||||
js::UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res)
|
||||
{
|
||||
return UrshOperation(cx, script, pc, lhs, rhs, res);
|
||||
return UrshOperation(cx, lhs, rhs, res);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -382,34 +382,22 @@ InitElementArray(JSContext *cx, jsbytecode *pc,
|
|||
HandleObject obj, uint32_t index, HandleValue value);
|
||||
|
||||
bool
|
||||
AddValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res);
|
||||
AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res);
|
||||
|
||||
bool
|
||||
SubValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res);
|
||||
SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res);
|
||||
|
||||
bool
|
||||
MulValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res);
|
||||
MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res);
|
||||
|
||||
bool
|
||||
DivValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res);
|
||||
DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res);
|
||||
|
||||
bool
|
||||
ModValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res);
|
||||
ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res);
|
||||
|
||||
bool
|
||||
UrshValues(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
MutableHandleValue lhs, MutableHandleValue rhs,
|
||||
Value *res);
|
||||
UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res);
|
||||
|
||||
template <bool strict>
|
||||
bool
|
||||
|
|
|
@ -2136,10 +2136,6 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
|||
cStats.typeInference.typeScripts,
|
||||
"Memory used by type sets associated with scripts.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("type-inference/type-results"),
|
||||
cStats.typeInference.typeResults,
|
||||
"Memory used by dynamic type results produced by scripts.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("type-inference/pending-arrays"),
|
||||
cStats.typeInference.pendingArrays,
|
||||
"Memory used for solving constraints during type inference.");
|
||||
|
|
Загрузка…
Ссылка в новой задаче