diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 3c8538c2926c..082382767771 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5723,11 +5723,24 @@ bool IonBuilder::jsop_newarray(uint32_t count) { JSObject *templateObject = inspector->getTemplateObject(pc); - if (!templateObject) + if (!templateObject) { + if (info().executionMode() == ArgumentsUsageAnalysis) { + MUnknownValue *unknown = MUnknownValue::New(alloc()); + current->add(unknown); + current->push(unknown); + return true; + } return abort("No template object for NEWARRAY"); + } JS_ASSERT(templateObject->is()); if (templateObject->type()->unknownProperties()) { + if (info().executionMode() == ArgumentsUsageAnalysis) { + MUnknownValue *unknown = MUnknownValue::New(alloc()); + current->add(unknown); + current->push(unknown); + return true; + } // We will get confused in jsop_initelem_array if we can't find the // type object being initialized. return abort("New array has unknown properties"); @@ -5778,8 +5791,15 @@ bool IonBuilder::jsop_newobject() { JSObject *templateObject = inspector->getTemplateObject(pc); - if (!templateObject) + if (!templateObject) { + if (info().executionMode() == ArgumentsUsageAnalysis) { + MUnknownValue *unknown = MUnknownValue::New(alloc()); + current->add(unknown); + current->push(unknown); + return true; + } return abort("No template object for NEWOBJECT"); + } JS_ASSERT(templateObject->is()); MConstant *templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject); @@ -5819,15 +5839,19 @@ IonBuilder::jsop_initelem_array() // intializer, and that arrays are marked as non-packed when writing holes // to them during initialization. bool needStub = false; - types::TypeObjectKey *initializer = obj->resultTypeSet()->getObject(0); - if (value->type() == MIRType_MagicHole) { - if (!initializer->hasFlags(constraints(), types::OBJECT_FLAG_NON_PACKED)) - needStub = true; - } else if (!initializer->unknownProperties()) { - types::HeapTypeSetKey elemTypes = initializer->property(JSID_VOID); - if (!TypeSetIncludes(elemTypes.maybeTypes(), value->type(), value->resultTypeSet())) { - elemTypes.freeze(constraints()); - needStub = true; + if (obj->isUnknownValue()) { + needStub = true; + } else { + types::TypeObjectKey *initializer = obj->resultTypeSet()->getObject(0); + if (value->type() == MIRType_MagicHole) { + if (!initializer->hasFlags(constraints(), types::OBJECT_FLAG_NON_PACKED)) + needStub = true; + } else if (!initializer->unknownProperties()) { + types::HeapTypeSetKey elemTypes = initializer->property(JSID_VOID); + if (!TypeSetIncludes(elemTypes.maybeTypes(), value->type(), value->resultTypeSet())) { + elemTypes.freeze(constraints()); + needStub = true; + } } } @@ -5888,20 +5912,28 @@ IonBuilder::jsop_initprop(PropertyName *name) MDefinition *value = current->pop(); MDefinition *obj = current->peek(-1); - JSObject *templateObject = obj->toNewObject()->templateObject(); + JSObject *templateObject = nullptr; + Shape *shape = nullptr; - Shape *shape = templateObject->lastProperty()->searchLinear(NameToId(name)); + bool useSlowPath = false; - if (!shape) { - // JSOP_NEWINIT becomes an MNewObject without preconfigured properties. - MInitProp *init = MInitProp::New(alloc(), obj, name, value); - current->add(init); - return resumeAfter(init); + if (obj->isUnknownValue()) { + useSlowPath = true; + } else { + templateObject = obj->toNewObject()->templateObject(); + shape = templateObject->lastProperty()->searchLinear(NameToId(name)); + + if (!shape) + useSlowPath = true; } if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &obj, name, &value, /* canModify = */ true)) { + useSlowPath = true; + } + + if (useSlowPath) { // JSOP_NEWINIT becomes an MNewObject without preconfigured properties. MInitProp *init = MInitProp::New(alloc(), obj, name, value); current->add(init); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 607f12177c3f..2120d0b5c764 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -3988,3 +3988,9 @@ LIRGenerator::visitArrayState(MArrayState *objState) // ArrayState nodes are always recovered on bailouts MOZ_CRASH("Unexpected ArrayState node during Lowering."); } + +bool +LIRGenerator::visitUnknownValue(MUnknownValue *ins) +{ + MOZ_CRASH("Can not lower unknown value."); +} diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 3f1d30a7e98b..dde4cb0aba43 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -278,6 +278,7 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitBeta(MBeta *ins); bool visitObjectState(MObjectState *ins); bool visitArrayState(MArrayState *ins); + bool visitUnknownValue(MUnknownValue *ins); }; } // namespace jit diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 4530dc3cfa5f..83f2e1be65d1 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -11709,6 +11709,21 @@ class MAsmJSCall MOZ_FINAL : public MVariadicInstruction } }; +class MUnknownValue : public MNullaryInstruction +{ + protected: + MUnknownValue() { + setResultType(MIRType_Value); + } + + public: + INSTRUCTION_HEADER(UnknownValue) + + static MUnknownValue *New(TempAllocator &alloc) { + return new(alloc) MUnknownValue(); + } +}; + #undef INSTRUCTION_HEADER void MUse::init(MDefinition *producer, MNode *consumer) diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index 569518fe10c5..361d1c784744 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -242,7 +242,8 @@ namespace jit { _(ForkJoinGetSlice) \ _(GuardThreadExclusive) \ _(InterruptCheckPar) \ - _(RecompileCheck) + _(RecompileCheck) \ + _(UnknownValue) // Forward declarations of MIR types. #define FORWARD_DECLARE(op) class M##op; diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index 907bbca2ebf3..23bd281182a2 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -341,6 +341,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor UNSAFE_OP(AsmJSParameter) UNSAFE_OP(AsmJSCall) DROP_OP(RecompileCheck) + UNSAFE_OP(UnknownValue) // It looks like this could easily be made safe: UNSAFE_OP(ConvertElementsToDoubles)