From 0ce5cf92d1a62cd5162896f6d49aec3cee299234 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 11 Sep 2014 13:37:46 -0700 Subject: [PATCH] Backout ce0afdc6ea1f (bug 1041688) for regressions. --- js/src/jit/Ion.cpp | 3 ++- js/src/jit/IonAnalysis.cpp | 4 +-- js/src/jit/IonBuilder.cpp | 49 ++++++++++++++++++++++++++++++------ js/src/jit/IonBuilder.h | 3 ++- js/src/jit/MCallOptimize.cpp | 3 ++- js/src/jit/MIR.cpp | 10 +++++--- js/src/jit/MIR.h | 6 +++-- js/src/jsinfer.cpp | 15 +++++++++++ js/src/jsinfer.h | 1 + 9 files changed, 77 insertions(+), 17 deletions(-) diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 44d950b2956..99bf66951af 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -2034,7 +2034,8 @@ IonCompile(JSContext *cx, JSScript *script, const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(optimizationLevel); const JitCompileOptions options(cx); - IonBuilder *builder = alloc->new_(CompileCompartment::get(cx->compartment()), + IonBuilder *builder = alloc->new_((JSContext *) nullptr, + CompileCompartment::get(cx->compartment()), options, temp, graph, constraints, inspector, info, optimizationInfo, baselineFrameInspector); diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 452be307066..88efbb69290 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -2792,7 +2792,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun, BaselineInspector inspector(script); const JitCompileOptions options(cx); - IonBuilder builder(CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints, + IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints, &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr); if (!builder.build()) { @@ -3019,7 +3019,7 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg) BaselineInspector inspector(script); const JitCompileOptions options(cx); - IonBuilder builder(CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints, + IonBuilder builder(nullptr, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints, &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr); if (!builder.build()) { diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index b6d6c69a2d8..a0321b3b3fd 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -106,7 +106,7 @@ jit::NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame, Compil return inspector; } -IonBuilder::IonBuilder(CompileCompartment *comp, +IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp, const JitCompileOptions &options, TempAllocator *temp, MIRGraph *graph, types::CompilerConstraintList *constraints, BaselineInspector *inspector, CompileInfo *info, @@ -115,6 +115,7 @@ IonBuilder::IonBuilder(CompileCompartment *comp, uint32_t loopDepth) : MIRGenerator(comp, options, temp, graph, info, optimizationInfo), backgroundCodegen_(nullptr), + analysisContext(analysisContext), baselineFrame_(baselineFrame), constraints_(constraints), analysis_(*temp, info->script()), @@ -146,6 +147,7 @@ IonBuilder::IonBuilder(CompileCompartment *comp, abortReason_ = AbortReason_Disable; JS_ASSERT(script()->hasBaselineScript() == (info->executionMode() != ArgumentsUsageAnalysis)); + JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis)); if (!info->executionModeIsAnalysis()) script()->baselineScript()->setIonCompiledOrInlined(); @@ -154,6 +156,7 @@ IonBuilder::IonBuilder(CompileCompartment *comp, void IonBuilder::clearForBackEnd() { + JS_ASSERT(!analysisContext); baselineFrame_ = nullptr; // The caches below allocate data from the malloc heap. Release this before @@ -346,6 +349,22 @@ IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo) if (!target->isInterpreted()) return DontInline(nullptr, "Non-interpreted target"); + // Allow constructing lazy scripts when performing the definite properties + // analysis, as baseline has not been used to warm the caller up yet. + if (target->isInterpreted() && info().executionMode() == DefinitePropertiesAnalysis) { + RootedScript script(analysisContext, target->getOrCreateScript(analysisContext)); + if (!script) + return InliningDecision_Error; + + if (!script->hasBaselineScript() && script->canBaselineCompile()) { + MethodStatus status = BaselineCompile(analysisContext, script); + if (status == Method_Error) + return InliningDecision_Error; + if (status != Method_Compiled) + return InliningDecision_DontInline; + } + } + if (!target->hasScript()) return DontInline(nullptr, "Lazy script"); @@ -4184,10 +4203,16 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target) AutoAccumulateReturns aar(graph(), returns); // Build the graph. - IonBuilder inlineBuilder(compartment, options, &alloc(), &graph(), constraints(), + IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(), &inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1, loopDepth_); if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) { + if (analysisContext && analysisContext->isExceptionPending()) { + JitSpew(JitSpew_Abort, "Inline builder raised exception."); + abortReason_ = AbortReason_Error; + return false; + } + // Inlining the callee failed. Mark the callee as uninlineable only if // the inlining was aborted for a non-exception reason. if (inlineBuilder.abortReason_ == AbortReason_Disable) { @@ -6418,6 +6443,8 @@ IonBuilder::testSingletonProperty(JSObject *obj, PropertyName *name) return nullptr; types::TypeObjectKey *objType = types::TypeObjectKey::get(obj); + if (analysisContext) + objType->ensureTrackedProperty(analysisContext, NameToId(name)); if (objType->unknownProperties()) return nullptr; @@ -6499,6 +6526,8 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr types::TypeObjectKey *object = types->getObject(i); if (!object) continue; + if (analysisContext) + object->ensureTrackedProperty(analysisContext, NameToId(name)); const Class *clasp = object->clasp(); if (!ClassHasEffectlessLookup(clasp, name) || ClassHasResolveHook(compartment, clasp, name)) @@ -6706,6 +6735,8 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc } types::TypeObjectKey *staticType = types::TypeObjectKey::get(staticObject); + if (analysisContext) + staticType->ensureTrackedProperty(analysisContext, NameToId(name)); if (staticType->unknownProperties()) { *psucceeded = false; @@ -6724,7 +6755,7 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc } types::TemporaryTypeSet *types = bytecodeTypes(pc); - BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), staticType, + BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), staticType, name, types, /* updateObserved = */ true); JSObject *singleton = types->getSingleton(); @@ -7540,7 +7571,8 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index) // Emit GetElementCache. types::TemporaryTypeSet *types = bytecodeTypes(pc); - BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, types); + BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj, + nullptr, types); // Always add a barrier if the index might be a string or symbol, so that // the cache can attach stubs for particular properties. @@ -7588,7 +7620,8 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index) AddObjectsForPropertyRead(obj, nullptr, types); } - BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, types); + BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj, + nullptr, types); bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj); // Reads which are on holes in the object do not have to bail out if @@ -8904,7 +8937,8 @@ IonBuilder::jsop_getprop(PropertyName *name) if (!getPropTryArgumentsCallee(&emitted, obj, name) || emitted) return emitted; - BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, name, types); + BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), + obj, name, types); // Always use a call if we are performing analysis and // not actually emitting code, to simplify later analysis. Also skip deeper @@ -9586,7 +9620,8 @@ IonBuilder::getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *na // Passing the inner object to GetProperty IC is safe, see the // needsOuterizedThisObject check in IsCacheableGetPropCallNative. - BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), inner, name, types); + BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), + inner, name, types); if (!getPropTryCache(emitted, inner, name, barrier, types) || *emitted) return *emitted; diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 4e692b2644c..1fc35b0eb24 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -214,7 +214,7 @@ class IonBuilder static int CmpSuccessors(const void *a, const void *b); public: - IonBuilder(CompileCompartment *comp, + IonBuilder(JSContext *analysisContext, CompileCompartment *comp, const JitCompileOptions &options, TempAllocator *temp, MIRGraph *graph, types::CompilerConstraintList *constraints, BaselineInspector *inspector, CompileInfo *info, @@ -865,6 +865,7 @@ class IonBuilder private: bool init(); + JSContext *analysisContext; BaselineFrameInspector *baselineFrame_; // Constraints for recording dependencies on type information. diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 530509da129..a07271ffa89 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -433,7 +433,8 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode) bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), types::OBJECT_FLAG_NON_PACKED); bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType()); - BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, returnTypes); + BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), + obj, nullptr, returnTypes); if (barrier != BarrierKind::NoBarrier) returnType = MIRType_Value; diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index b2d7c607885..145558a724b 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -3667,7 +3667,8 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, } BarrierKind -jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, +jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx, + types::CompilerConstraintList *constraints, types::TypeObjectKey *object, PropertyName *name, types::TemporaryTypeSet *observed, bool updateObserved) { @@ -3687,6 +3688,8 @@ jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, break; types::TypeObjectKey *typeObj = types::TypeObjectKey::get(obj); + if (propertycx) + typeObj->ensureTrackedProperty(propertycx, NameToId(name)); if (!typeObj->unknownProperties()) { types::HeapTypeSetKey property = typeObj->property(NameToId(name)); @@ -3712,7 +3715,8 @@ jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, } BarrierKind -jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, +jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx, + types::CompilerConstraintList *constraints, MDefinition *obj, PropertyName *name, types::TemporaryTypeSet *observed) { @@ -3729,7 +3733,7 @@ jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, for (size_t i = 0; i < types->getObjectCount(); i++) { types::TypeObjectKey *object = types->getObject(i); if (object) { - BarrierKind kind = PropertyReadNeedsTypeBarrier(constraints, object, name, + BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, object, name, observed, updateObserved); if (kind == BarrierKind::TypeSet) return BarrierKind::TypeSet; diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 6717ad46cb9..9cc03f5c7a6 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -11772,10 +11772,12 @@ bool ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints, bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints, MDefinition *obj); MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj); -BarrierKind PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, +BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx, + types::CompilerConstraintList *constraints, types::TypeObjectKey *object, PropertyName *name, types::TemporaryTypeSet *observed, bool updateObserved); -BarrierKind PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints, +BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx, + types::CompilerConstraintList *constraints, MDefinition *obj, PropertyName *name, types::TemporaryTypeSet *observed); BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints, diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 9fa46541006..6e221106feb 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1091,6 +1091,21 @@ TypeObjectKey::property(jsid id) return property; } +void +TypeObjectKey::ensureTrackedProperty(JSContext *cx, jsid id) +{ + // If we are accessing a lazily defined property which actually exists in + // the VM and has not been instantiated yet, instantiate it now if we are + // on the main thread and able to do so. + if (!JSID_IS_VOID(id) && !JSID_IS_EMPTY(id)) { + JS_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); + if (JSObject *obj = singleton()) { + if (obj->isNative() && obj->nativeLookupPure(id)) + EnsureTrackPropertyTypes(cx, obj, id); + } + } +} + bool HeapTypeSetKey::instantiate(JSContext *cx) { diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index f6d4b99fc8d..e9ca2a65f47 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -1465,6 +1465,7 @@ struct TypeObjectKey void watchStateChangeForInlinedCall(CompilerConstraintList *constraints); void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints); HeapTypeSetKey property(jsid id); + void ensureTrackedProperty(JSContext *cx, jsid id); TypeObject *maybeType(); };