Example #1
0
    MethodStatus compileForParallelExecution() {
        // The kernel should be a self-hosted function.
        if (!fun_->isFunction())
            return Method_Skipped;

        RootedFunction callee(cx_, fun_->toFunction());

        if (!callee->isInterpreted() || !callee->isSelfHostedBuiltin())
            return Method_Skipped;

        if (callee->isInterpretedLazy() && !callee->initializeLazyScript(cx_))
            return Method_Error;

        // If this function has not been run enough to enable parallel
        // execution, perform a warmup.
        RootedScript script(cx_, callee->nonLazyScript());
        if (script->getUseCount() < js_IonOptions.usesBeforeCompileParallel) {
            if (!warmupForParallelExecution())
                return Method_Error;
        }

        if (script->hasParallelIonScript() &&
            !script->parallelIonScript()->hasInvalidatedCallTarget())
        {
            Spew(SpewOps, "Already compiled");
            return Method_Compiled;
        }

        Spew(SpewOps, "Compiling all reachable functions");

        ParallelCompileContext compileContext(cx_);
        if (!compileContext.appendToWorklist(script))
            return Method_Error;

        MethodStatus status = compileContext.compileTransitively();
        if (status != Method_Compiled)
            return status;

        // it can happen that during transitive compilation, our
        // callee's parallel ion script is invalidated or GC'd. So
        // before we declare success, double check that it's still
        // compiled!
        if (!callee->nonLazyScript()->hasParallelIonScript())
            return Method_Skipped;

        return Method_Compiled;
    }
Example #2
0
    virtual bool parallel(ForkJoinSlice &slice) {
#ifndef JS_ION
        JS_NOT_REACHED("Parallel execution without ion");
        return false;
#else
        Spew(SpewOps, "Up");

        // Make a new IonContext for the slice, which is needed if we need to
        // re-enter the VM.
        IonContext icx(cx_, NULL);

        JS_ASSERT(pendingInvalidations[slice.sliceId] == NULL);

        JS_ASSERT(fun_->isFunction());
        RootedFunction callee(cx_, fun_->toFunction());
        if (!callee->nonLazyScript()->hasParallelIonScript()) {
            // Sometimes, particularly with GCZeal, the parallel ion
            // script can be collected between starting the parallel
            // op and reaching this point.  In that case, we just fail
            // and fallback.
            Spew(SpewOps, "Down (Script no longer present)");
            return false;
        }

        ParallelIonInvoke<3> fii(cx_, callee, 3);

        fii.args[0] = Int32Value(slice.sliceId);
        fii.args[1] = Int32Value(slice.numSlices);
        fii.args[2] = BooleanValue(false);

        bool ok = fii.invoke(cx_);
        JS_ASSERT(ok == !slice.abortedScript);
        if (!ok) {
            JSScript *script = slice.abortedScript;
            Spew(SpewBailouts, "Aborted script: %p (hasParallelIonScript? %d)",
                 script, script->hasParallelIonScript());
            JS_ASSERT(script->hasParallelIonScript());
            pendingInvalidations[slice.sliceId] = script;
        }

        Spew(SpewOps, "Down");

        return ok;
#endif // JS_ION
    }