--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1642,41 +1642,52 @@ TryEliminateTypeBarrierFromTest(MTypeBar
// Disregard the possible unbox added before the Typebarrier for checking.
MDefinition *input = barrier->input();
MUnbox *inputUnbox = nullptr;
if (input->isUnbox() && input->toUnbox()->mode() != MUnbox::Fallible) {
inputUnbox = input->toUnbox();
input = inputUnbox->input();
}
- MDefinition *subject = nullptr;
- bool removeUndefined;
- bool removeNull;
- test->filtersUndefinedOrNull(direction == TRUE_BRANCH, &subject, &removeUndefined, &removeNull);
+ if (test->getOperand(0) == input && direction == TRUE_BRANCH) {
+ *eliminated = true;
+ if (inputUnbox)
+ inputUnbox->makeInfallible();
+ barrier->replaceAllUsesWith(barrier->input());
+ return;
+ }
- // The Test doesn't filter undefined nor null.
- if (!subject)
- return;
-
- // Make sure the subject equals the input to the TypeBarrier.
- if (subject != input)
+ if (!test->getOperand(0)->isCompare())
return;
- // When the TypeBarrier filters undefined, the test must at least also do,
- // this, before the TypeBarrier can get removed.
- if (!removeUndefined && filtersUndefined)
+ MCompare *compare = test->getOperand(0)->toCompare();
+ MCompare::CompareType compareType = compare->compareType();
+
+ if (compareType != MCompare::Compare_Undefined && compareType != MCompare::Compare_Null)
+ return;
+ if (compare->getOperand(0) != input)
return;
- // When the TypeBarrier filters null, the test must at least also do,
- // this, before the TypeBarrier can get removed.
- if (!removeNull && filtersNull)
+ JSOp op = compare->jsop();
+ JS_ASSERT(op == JSOP_EQ || op == JSOP_STRICTEQ ||
+ op == JSOP_NE || op == JSOP_STRICTNE);
+
+ if ((direction == TRUE_BRANCH) != (op == JSOP_NE || op == JSOP_STRICTNE))
return;
- // Eliminate the TypeBarrier. The possible TypeBarrier unboxing is kept,
- // but made infallible.
+ // A test 'if (x.f != null)' or 'if (x.f != undefined)' filters both null
+ // and undefined. If strict equality is used, only the specified rhs is
+ // tested for.
+ if (op == JSOP_STRICTEQ || op == JSOP_STRICTNE) {
+ if (compareType == MCompare::Compare_Undefined && !filtersUndefined)
+ return;
+ if (compareType == MCompare::Compare_Null && !filtersNull)
+ return;
+ }
+
*eliminated = true;
if (inputUnbox)
inputUnbox->makeInfallible();
barrier->replaceAllUsesWith(barrier->input());
}
static bool
TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -192,55 +192,50 @@ IonBuilder::spew(const char *message)
static inline int32_t
GetJumpOffset(jsbytecode *pc)
{
JS_ASSERT(js_CodeSpec[JSOp(*pc)].type() == JOF_JUMP);
return GET_JUMP_OFFSET(pc);
}
IonBuilder::CFGState
-IonBuilder::CFGState::If(jsbytecode *join, MTest *test)
+IonBuilder::CFGState::If(jsbytecode *join, MBasicBlock *ifFalse)
{
CFGState state;
state.state = IF_TRUE;
state.stopAt = join;
- state.branch.ifFalse = test->ifFalse();
- state.branch.test = test;
+ state.branch.ifFalse = ifFalse;
return state;
}
IonBuilder::CFGState
-IonBuilder::CFGState::IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MTest *test)
-{
- MBasicBlock *ifFalse = test->ifFalse();
-
+IonBuilder::CFGState::IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MBasicBlock *ifFalse)
+{
CFGState state;
// If the end of the false path is the same as the start of the
// false path, then the "else" block is empty and we can devolve
// this to the IF_TRUE case. We handle this here because there is
// still an extra GOTO on the true path and we want stopAt to point
// there, whereas the IF_TRUE case does not have the GOTO.
state.state = (falseEnd == ifFalse->pc())
? IF_TRUE_EMPTY_ELSE
: IF_ELSE_TRUE;
state.stopAt = trueEnd;
state.branch.falseEnd = falseEnd;
state.branch.ifFalse = ifFalse;
- state.branch.test = test;
return state;
}
IonBuilder::CFGState
IonBuilder::CFGState::AndOr(jsbytecode *join, MBasicBlock *joinStart)
{
CFGState state;
state.state = AND_OR;
state.stopAt = join;
state.branch.ifFalse = joinStart;
- state.branch.test = nullptr;
return state;
}
IonBuilder::CFGState
IonBuilder::CFGState::TableSwitch(jsbytecode *exitpc, MTableSwitch *ins)
{
CFGState state;
state.state = TABLE_SWITCH;
@@ -1937,20 +1932,16 @@ IonBuilder::processIfElseTrueEnd(CFGStat
// We've reached the end of the true branch of an if-else. Don't
// create an edge yet, just transition to parsing the false branch.
state.state = CFGState::IF_ELSE_FALSE;
state.branch.ifTrue = current;
state.stopAt = state.branch.falseEnd;
pc = state.branch.ifFalse->pc();
setCurrentAndSpecializePhis(state.branch.ifFalse);
graph().moveBlockToEnd(current);
-
- if (state.branch.test)
- filterTypesAtTest(state.branch.test);
-
return ControlStatus_Jumped;
}
IonBuilder::ControlStatus
IonBuilder::processIfElseFalseEnd(CFGState &state)
{
// Update the state to have the latest block from the false path.
state.branch.ifFalse = current;
@@ -3052,69 +3043,16 @@ IonBuilder::tableSwitch(JSOp op, jssrcno
if (!cfgStack_.append(state))
return ControlStatus_Error;
pc = current->pc();
return ControlStatus_Jumped;
}
bool
-IonBuilder::filterTypesAtTest(MTest *test)
-{
- JS_ASSERT(test->ifTrue() == current || test->ifFalse() == current);
-
- bool trueBranch = test->ifTrue() == current;
-
- MDefinition *subject = nullptr;
- bool removeUndefined;
- bool removeNull;
-
- test->filtersUndefinedOrNull(trueBranch, &subject, &removeUndefined, &removeNull);
-
- // The test filters no undefined or null.
- if (!subject)
- return true;
-
- // There is no TypeSet that can get filtered.
- if (!subject->resultTypeSet())
- return true;
-
- // Only do this optimization if the typeset does contains null or undefined.
- if ((removeUndefined && subject->resultTypeSet()->hasType(types::Type::UndefinedType())) ||
- (removeNull && subject->resultTypeSet()->hasType(types::Type::NullType())))
- {
- return true;
- }
-
- // Find all values on the stack that correspond to the subject
- // and replace it with a MIR with filtered TypeSet information.
- // Create the replacement MIR lazily upon first occurence.
- MDefinition *replace = nullptr;
- for (uint32_t i = 0; i < current->stackDepth(); i++) {
- if (current->getSlot(i) != subject)
- continue;
-
- // Create replacement MIR with filtered TypesSet.
- if (!replace) {
- types::TemporaryTypeSet *type =
- subject->resultTypeSet()->filter(alloc_->lifoAlloc(), removeUndefined,
- removeNull);
- if (!type)
- return false;
-
- replace = ensureDefiniteTypeSet(subject, type);
- }
-
- current->setSlot(i, replace);
- }
-
- return true;
-}
-
-bool
IonBuilder::jsop_label()
{
JS_ASSERT(JSOp(*pc) == JSOP_LABEL);
jsbytecode *endpc = pc + GET_JUMP_OFFSET(pc);
JS_ASSERT(endpc > pc);
ControlFlowInfo label(cfgStack_.length(), endpc);
@@ -3522,17 +3460,17 @@ IonBuilder::jsop_ifeq(JSOp op)
// ...
// Z: ... ; join
//
// We want to parse the bytecode as if we were parsing the AST, so for the
// IF_ELSE/COND cases, we use the source note and follow the GOTO. For the
// IF case, the IFEQ offset is the join point.
switch (SN_TYPE(sn)) {
case SRC_IF:
- if (!cfgStack_.append(CFGState::If(falseStart, test)))
+ if (!cfgStack_.append(CFGState::If(falseStart, ifFalse)))
return false;
break;
case SRC_IF_ELSE:
case SRC_COND:
{
// Infer the join point from the JSOP_GOTO[X] sitting here, then
// assert as we much we can that this is the right GOTO.
@@ -3541,32 +3479,29 @@ IonBuilder::jsop_ifeq(JSOp op)
JS_ASSERT(trueEnd < falseStart);
JS_ASSERT(JSOp(*trueEnd) == JSOP_GOTO);
JS_ASSERT(!info().getNote(gsn, trueEnd));
jsbytecode *falseEnd = trueEnd + GetJumpOffset(trueEnd);
JS_ASSERT(falseEnd > trueEnd);
JS_ASSERT(falseEnd >= falseStart);
- if (!cfgStack_.append(CFGState::IfElse(trueEnd, falseEnd, test)))
+ if (!cfgStack_.append(CFGState::IfElse(trueEnd, falseEnd, ifFalse)))
return false;
break;
}
default:
MOZ_ASSUME_UNREACHABLE("unexpected source note type");
}
// Switch to parsing the true branch. Note that no PC update is needed,
// it's the next instruction.
setCurrentAndSpecializePhis(ifTrue);
- // Filter the types in the true branch.
- filterTypesAtTest(test);
-
return true;
}
bool
IonBuilder::jsop_try()
{
JS_ASSERT(JSOp(*pc) == JSOP_TRY);
@@ -6365,36 +6300,16 @@ IonBuilder::ensureDefiniteType(MDefiniti
break;
}
}
current->add(replace);
return replace;
}
-MDefinition *
-IonBuilder::ensureDefiniteTypeSet(MDefinition *def, types::TemporaryTypeSet *types)
-{
- // We cannot arbitrarily add a typeset to a definition. It can be shared
- // in another path. So we always need to create a new MIR.
-
- // Use ensureDefiniteType to do unboxing. If that happened the type can
- // be added on the newly created unbox operation.
- MDefinition *replace = ensureDefiniteType(def, types->getKnownTypeTag());
- if (replace != def) {
- replace->setResultTypeSet(types);
- return replace;
- }
-
- // Create a NOP mir instruction to filter the typeset.
- MFilterTypeSet *filter = MFilterTypeSet::New(alloc(), def, types);
- current->add(filter);
- return filter;
-}
-
static size_t
NumFixedSlots(JSObject *object)
{
// Note: we can't use object->numFixedSlots() here, as this will read the
// shape and can race with the main thread if we are building off thread.
// The allocation kind and object class (which goes through the type) can
// be read freely, however.
gc::AllocKind kind = object->tenuredGetAllocKind();
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -105,17 +105,16 @@ class IonBuilder : public MIRGenerator
jsbytecode *stopAt; // Bytecode at which to stop the processing loop.
// For if structures, this contains branch information.
union {
struct {
MBasicBlock *ifFalse;
jsbytecode *falseEnd;
MBasicBlock *ifTrue; // Set when the end of the true path is reached.
- MTest *test;
} branch;
struct {
// Common entry point.
MBasicBlock *entry;
// Whether OSR is being performed for this loop.
bool osr;
@@ -196,18 +195,18 @@ class IonBuilder : public MIRGenerator
case FOR_LOOP_BODY:
case FOR_LOOP_UPDATE:
return true;
default:
return false;
}
}
- static CFGState If(jsbytecode *join, MTest *test);
- static CFGState IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MTest *test);
+ static CFGState If(jsbytecode *join, MBasicBlock *ifFalse);
+ static CFGState IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MBasicBlock *ifFalse);
static CFGState AndOr(jsbytecode *join, MBasicBlock *joinStart);
static CFGState TableSwitch(jsbytecode *exitpc, MTableSwitch *ins);
static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
static CFGState Label(jsbytecode *exitpc);
static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
};
static int CmpSuccessors(const void *a, const void *b);
@@ -332,37 +331,31 @@ class IonBuilder : public MIRGenerator
void rewriteParameters();
bool initScopeChain(MDefinition *callee = nullptr);
bool initArgumentsObject();
bool pushConstant(const Value &v);
MConstant *constant(const Value &v);
MConstant *constantInt(int32_t i);
- // Filter the type information at tests
- bool filterTypesAtTest(MTest *test);
-
// Add a guard which ensure that the set of type which goes through this
// generated code correspond to the observed types for the bytecode.
bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needBarrier);
// As pushTypeBarrier, but will compute the needBarrier boolean itself based
// on observed and the JSFunction that we're planning to call. The
// JSFunction must be a DOM method or getter.
bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
// If definiteType is not known or def already has the right type, just
// returns def. Otherwise, returns an MInstruction that has that definite
// type, infallibly unboxing ins as needed. The new instruction will be
// added to |current| in this case.
MDefinition *ensureDefiniteType(MDefinition* def, JSValueType definiteType);
- // Creates a MDefinition based on the given def improved with type as TypeSet.
- MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);
-
JSObject *getSingletonPrototype(JSFunction *target);
MDefinition *createThisScripted(MDefinition *callee);
MDefinition *createThisScriptedSingleton(JSFunction *target, MDefinition *callee);
MDefinition *createThis(JSFunction *target, MDefinition *callee);
MInstruction *createDeclEnvObject(MDefinition *callee, MDefinition *scopeObj);
MInstruction *createCallObject(MDefinition *callee, MDefinition *scopeObj);
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2192,22 +2192,16 @@ LIRGenerator::visitStoreSlot(MStoreSlot
return add(new(alloc()) LStoreSlotT(useRegister(ins->slots()), useRegisterOrConstant(ins->value())),
ins);
}
return true;
}
bool
-LIRGenerator::visitFilterTypeSet(MFilterTypeSet *ins)
-{
- return redefine(ins, ins->input());
-}
-
-bool
LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
{
// Requesting a non-GC pointer is safe here since we never re-enter C++
// from inside a type barrier test.
const types::TemporaryTypeSet *types = ins->resultTypeSet();
bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -161,17 +161,16 @@ class LIRGenerator : public LIRGenerator
bool visitMaybeToDoubleElement(MMaybeToDoubleElement *ins);
bool visitLoadSlot(MLoadSlot *ins);
bool visitFunctionEnvironment(MFunctionEnvironment *ins);
bool visitForkJoinContext(MForkJoinContext *ins);
bool visitGuardThreadExclusive(MGuardThreadExclusive *ins);
bool visitInterruptCheck(MInterruptCheck *ins);
bool visitInterruptCheckPar(MInterruptCheckPar *ins);
bool visitStoreSlot(MStoreSlot *ins);
- bool visitFilterTypeSet(MFilterTypeSet *ins);
bool visitTypeBarrier(MTypeBarrier *ins);
bool visitMonitorTypes(MMonitorTypes *ins);
bool visitPostWriteBarrier(MPostWriteBarrier *ins);
bool visitArrayLength(MArrayLength *ins);
bool visitSetArrayLength(MSetArrayLength *ins);
bool visitTypedArrayLength(MTypedArrayLength *ins);
bool visitTypedArrayElements(MTypedArrayElements *ins);
bool visitTypedObjectElements(MTypedObjectElements *ins);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -220,22 +220,16 @@ MaybeCallable(MDefinition *op)
types::TemporaryTypeSet *types = op->resultTypeSet();
if (!types)
return true;
return types->maybeCallable();
}
-MTest *
-MTest::New(TempAllocator &alloc, MDefinition *ins, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
-{
- return new(alloc) MTest(ins, ifTrue, ifFalse);
-}
-
void
MTest::infer()
{
JS_ASSERT(operandMightEmulateUndefined());
if (!MaybeEmulatesUndefined(getOperand(0)))
markOperandCantEmulateUndefined();
}
@@ -247,42 +241,16 @@ MTest::foldsTo(TempAllocator &alloc, boo
if (op->isNot())
return MTest::New(alloc, op->toNot()->operand(), ifFalse(), ifTrue());
return this;
}
void
-MTest::filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
- bool *filtersNull)
-{
- MDefinition *ins = getOperand(0);
- if (ins->isCompare()) {
- ins->toCompare()->filtersUndefinedOrNull(trueBranch, subject, filtersUndefined, filtersNull);
- return;
- }
-
- if (!trueBranch && ins->isNot()) {
- *subject = ins->getOperand(0);
- *filtersUndefined = *filtersNull = true;
- return;
- }
-
- if (trueBranch) {
- *subject = ins;
- *filtersUndefined = *filtersNull = true;
- return;
- }
-
- *filtersUndefined = *filtersNull = false;
- *subject = nullptr;
-}
-
-void
MDefinition::printOpcode(FILE *fp) const
{
PrintOpcodeName(fp, op());
for (size_t j = 0, e = numOperands(); j < e; j++) {
fprintf(fp, " ");
getOperand(j)->printName(fp);
}
}
@@ -839,16 +807,22 @@ MFloor::trySpecializeFloat32(TempAllocat
}
if (type() == MIRType_Double)
setResultType(MIRType_Float32);
setPolicyType(MIRType_Float32);
}
+MTest *
+MTest::New(TempAllocator &alloc, MDefinition *ins, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
+{
+ return new(alloc) MTest(ins, ifTrue, ifFalse);
+}
+
MCompare *
MCompare::New(TempAllocator &alloc, MDefinition *left, MDefinition *right, JSOp op)
{
return new(alloc) MCompare(left, right, op);
}
MCompare *
MCompare::NewAsmJS(TempAllocator &alloc, MDefinition *left, MDefinition *right, JSOp op,
@@ -2574,47 +2548,16 @@ MCompare::trySpecializeFloat32(TempAlloc
if (lhs->type() == MIRType_Float32)
ConvertDefinitionToDouble<0>(alloc, lhs, this);
if (rhs->type() == MIRType_Float32)
ConvertDefinitionToDouble<1>(alloc, rhs, this);
}
}
void
-MCompare::filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
- bool *filtersNull)
-{
- *filtersNull = *filtersUndefined = false;
- *subject = nullptr;
-
- if (compareType() != Compare_Undefined && compareType() != Compare_Null)
- return;
-
- JS_ASSERT(jsop() == JSOP_STRICTNE || jsop() == JSOP_NE ||
- jsop() == JSOP_STRICTEQ || jsop() == JSOP_EQ);
-
- // JSOP_*NE only removes undefined/null from if/true branch
- if (!trueBranch && (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE))
- return;
-
- // JSOP_*EQ only removes undefined/null from else/false branch
- if (trueBranch && (jsop() == JSOP_STRICTEQ || jsop() == JSOP_EQ))
- return;
-
- if (jsop() == JSOP_STRICTEQ || jsop() == JSOP_STRICTNE) {
- *filtersUndefined = compareType() == Compare_Undefined;
- *filtersNull = compareType() == Compare_Null;
- } else {
- *filtersUndefined = *filtersNull = true;
- }
-
- *subject = lhs();
-}
-
-void
MNot::infer()
{
JS_ASSERT(operandMightEmulateUndefined());
if (!MaybeEmulatesUndefined(getOperand(0)))
markOperandCantEmulateUndefined();
}
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1316,18 +1316,16 @@ class MTest
return this;
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
void infer();
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
- void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
- bool *filtersNull);
void markOperandCantEmulateUndefined() {
operandMightEmulateUndefined_ = false;
}
bool operandMightEmulateUndefined() const {
return operandMightEmulateUndefined_;
}
#ifdef DEBUG
@@ -2275,18 +2273,16 @@ class MCompare
INSTRUCTION_HEADER(Compare)
static MCompare *New(TempAllocator &alloc, MDefinition *left, MDefinition *right, JSOp op);
static MCompare *NewAsmJS(TempAllocator &alloc, MDefinition *left, MDefinition *right, JSOp op,
CompareType compareType);
bool tryFold(bool *result);
bool evaluateConstantOperands(bool *result);
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
- void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
- bool *filtersNull);
void infer(BaselineInspector *inspector, jsbytecode *pc);
CompareType compareType() const {
return compareType_;
}
bool isInt32Comparison() const {
return compareType() == Compare_Int32 ||
compareType() == Compare_Int32MaybeCoerceBoth ||
@@ -8735,47 +8731,16 @@ class MGuardThreadExclusive
AliasSet getAliasSet() const {
return AliasSet::None();
}
bool possiblyCalls() const {
return true;
}
};
-class MFilterTypeSet
- : public MUnaryInstruction
-{
- MFilterTypeSet(MDefinition *def, types::TemporaryTypeSet *types)
- : MUnaryInstruction(def)
- {
- JS_ASSERT(!types->unknown());
-
- MIRType type = MIRTypeFromValueType(types->getKnownTypeTag());
- setResultType(type);
- setResultTypeSet(types);
- }
-
- public:
- INSTRUCTION_HEADER(FilterTypeSet)
-
- static MFilterTypeSet *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types) {
- return new(alloc) MFilterTypeSet(def, types);
- }
-
- bool congruentTo(MDefinition *def) const {
- return false;
- }
- AliasSet getAliasSet() const {
- return AliasSet::None();
- }
- virtual bool neverHoist() const {
- return resultTypeSet()->empty();
- }
-};
-
// Given a value, guard that the value is in a particular TypeSet, then returns
// that value.
class MTypeBarrier
: public MUnaryInstruction,
public TypeBarrierPolicy
{
MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types)
: MUnaryInstruction(def)
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -109,17 +109,16 @@ namespace jit {
_(Slots) \
_(Elements) \
_(ConstantElements) \
_(ConvertElementsToDoubles) \
_(MaybeToDoubleElement) \
_(LoadSlot) \
_(StoreSlot) \
_(FunctionEnvironment) \
- _(FilterTypeSet) \
_(TypeBarrier) \
_(MonitorTypes) \
_(PostWriteBarrier) \
_(GetPropertyCache) \
_(GetPropertyPolymorphic) \
_(SetPropertyPolymorphic) \
_(GetElementCache) \
_(SetElementCache) \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -196,17 +196,16 @@ class ParallelSafetyVisitor : public MIn
CUSTOM_OP(Lambda)
UNSAFE_OP(ImplicitThis)
SAFE_OP(Slots)
SAFE_OP(Elements)
SAFE_OP(ConstantElements)
SAFE_OP(LoadSlot)
WRITE_GUARDED_OP(StoreSlot, slots)
SAFE_OP(FunctionEnvironment) // just a load of func env ptr
- SAFE_OP(FilterTypeSet)
SAFE_OP(TypeBarrier) // causes a bailout if the type is not found: a-ok with us
SAFE_OP(MonitorTypes) // causes a bailout if the type is not found: a-ok with us
UNSAFE_OP(PostWriteBarrier)
SAFE_OP(GetPropertyCache)
SAFE_OP(GetPropertyPolymorphic)
UNSAFE_OP(SetPropertyPolymorphic)
SAFE_OP(GetElementCache)
WRITE_GUARDED_OP(SetElementCache, object)
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -487,32 +487,16 @@ TemporaryTypeSet *
TypeSet::clone(LifoAlloc *alloc) const
{
TemporaryTypeSet *res = alloc->new_<TemporaryTypeSet>();
if (!res || !clone(alloc, res))
return nullptr;
return res;
}
-TemporaryTypeSet *
-TypeSet::filter(LifoAlloc *alloc, bool filterUndefined, bool filterNull) const
-{
- TemporaryTypeSet *res = clone(alloc);
- if (!res)
- return nullptr;
-
- if (filterUndefined)
- res->flags = flags & ~TYPE_FLAG_UNDEFINED;
-
- if (filterNull)
- res->flags = flags & ~TYPE_FLAG_NULL;
-
- return res;
-}
-
/* static */ TemporaryTypeSet *
TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
{
TemporaryTypeSet *res = alloc->new_<TemporaryTypeSet>(a->baseFlags() | b->baseFlags(),
static_cast<TypeObjectKey**>(nullptr));
if (!res)
return nullptr;
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -574,19 +574,16 @@ class TypeSet
/* Forward all types in this set to the specified constraint. */
void addTypesToConstraint(JSContext *cx, TypeConstraint *constraint);
// Clone a type set into an arbitrary allocator.
TemporaryTypeSet *clone(LifoAlloc *alloc) const;
bool clone(LifoAlloc *alloc, TemporaryTypeSet *result) const;
- // Create a new TemporaryTypeSet where undefined and/or null has been filtered out.
- TemporaryTypeSet *filter(LifoAlloc *alloc, bool filterUndefined, bool filterNull) const;
-
protected:
uint32_t baseObjectCount() const {
return (flags & TYPE_FLAG_OBJECT_COUNT_MASK) >> TYPE_FLAG_OBJECT_COUNT_SHIFT;
}
inline void setBaseObjectCount(uint32_t count);
inline void clearObjects();
};