Example #1
0
bool
TypeInferenceOracle::propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id)
{
    if (script->analysis()->getCode(pc).notIdempotent)
        return false;

    if (id != MakeTypeId(cx, id))
        return false;

    StackTypeSet *types = script->analysis()->poppedTypes(pc, 0);
    if (!types || types->unknownObject())
        return false;

    for (unsigned i = 0; i < types->getObjectCount(); i++) {
        if (types->getSingleObject(i))
            return false;

        if (TypeObject *obj = types->getTypeObject(i)) {
            if (obj->unknownProperties())
                return false;

            // Check if the property has been reconfigured or is a getter.
            HeapTypeSet *propertyTypes = obj->getProperty(cx, id, false);
            if (!propertyTypes || propertyTypes->isOwnProperty(cx, obj, true))
                return false;
        }
    }

    return true;
}
Example #2
0
    void beginCompile(HandleScript script) {
        if (!active[SpewCompile])
            return;

        spew(SpewCompile, "COMPILE %p:%s:%u", script.get(), script->filename(), script->lineno);
        depth++;
    }
Example #3
0
static bool
FilterContainsLocation(HandleScript function)
{
    static const char *filter = getenv("IONFILTER");

    // If there is no filter we accept all outputs.
    if (!filter || !filter[0])
        return true;

    // Disable asm.js output when filter is set.
    if (!function)
        return false;

    const char *filename = function->filename();
    const size_t line = function->lineno();
    const size_t filelen = strlen(filename);
    const char *index = strstr(filter, filename);
    while (index) {
        if (index == filter || index[-1] == ',') {
            if (index[filelen] == 0 || index[filelen] == ',')
                return true;
            if (index[filelen] == ':' && line != size_t(-1)) {
                size_t read_line = strtoul(&index[filelen + 1], nullptr, 10);
                if (read_line == line)
                    return true;
            }
        }
        index = strstr(index + filelen, filename);
    }
    return false;
}
Example #4
0
bool
TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc)
{
    JS_ASSERT(types::IsInlinableCall(pc));

    Bytecode *code = caller->analysis()->maybeCode(pc);
    if (code->monitoredTypes || code->monitoredTypesReturn || caller->analysis()->typeBarriers(cx, pc))
        return false;
    return true;
}
Example #5
0
JS_DumpPCCounts(JSContext *cx, HandleScript script)
{
    JS_ASSERT(script->hasScriptCounts());

    Sprinter sprinter(cx);
    if (!sprinter.init())
        return;

    fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno());
    js_DumpPCCounts(cx, script, &sprinter);
    fputs(sprinter.string(), stdout);
    fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno());
}
Example #6
0
static bool
MaybeCheckEvalFreeVariables(ExclusiveContext *cxArg, HandleScript evalCaller, HandleObject scopeChain,
                            Parser<FullParseHandler> &parser,
                            ParseContext<FullParseHandler> &pc)
{
    if (!evalCaller || !evalCaller->functionOrCallerFunction())
        return true;

    // Eval scripts are only compiled on the main thread.
    JSContext *cx = cxArg->asJSContext();

    // Watch for uses of 'arguments' within the evaluated script, both as
    // free variables and as variables redeclared with 'var'.
    RootedFunction fun(cx, evalCaller->functionOrCallerFunction());
    HandlePropertyName arguments = cx->names().arguments;
    for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) {
        if (r.front().key() == arguments) {
            if (!CheckArgumentsWithinEval(cx, parser, fun))
                return false;
        }
    }
    for (AtomDefnListMap::Range r = pc.decls().all(); !r.empty(); r.popFront()) {
        if (r.front().key() == arguments) {
            if (!CheckArgumentsWithinEval(cx, parser, fun))
                return false;
        }
    }

    // If the eval'ed script contains any debugger statement, force construction
    // of arguments objects for the caller script and any other scripts it is
    // transitively nested inside. The debugger can access any variable on the
    // scope chain.
    if (pc.sc->hasDebuggerStatement()) {
        RootedObject scope(cx, scopeChain);
        while (scope->is<ScopeObject>() || scope->is<DebugScopeObject>()) {
            if (scope->is<CallObject>() && !scope->as<CallObject>().isForEval()) {
                RootedScript script(cx, scope->as<CallObject>().callee().getOrCreateScript(cx));
                if (!script)
                    return false;
                if (script->argumentsHasVarBinding()) {
                    if (!JSScript::argumentsOptimizationFailed(cx, script))
                        return false;
                }
            }
            scope = scope->enclosingScope();
        }
    }

    return true;
}
bool
TypeInferenceOracle::elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *arrayType)
{
    // Check whether the object is a typed array and index is int32 or double.
    StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1);
    StackTypeSet *id = DropUnrooted(script)->analysis()->poppedTypes(pc, 0);

    JSValueType idType = id->getKnownTypeTag();
    if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
        return false;

    *arrayType = obj->getTypedArrayType();
    if (*arrayType == TypedArray::TYPE_MAX)
        return false;

    JS_ASSERT(*arrayType >= 0 && *arrayType < TypedArray::TYPE_MAX);

    // Unlike dense arrays, the types of elements in typed arrays are not
    // guaranteed to be present in the object's type, and we need to use
    // knowledge about the possible contents of the array vs. the types
    // that have been read out of it to figure out how to do the load.
    types::TypeSet *result = propertyRead(script, pc);
    if (*arrayType == TypedArray::TYPE_FLOAT32 || *arrayType == TypedArray::TYPE_FLOAT64) {
        if (!result->hasType(types::Type::DoubleType()))
            return false;
    } else {
        if (!result->hasType(types::Type::Int32Type()))
            return false;
    }

    return true;
}
Example #8
0
bool
TypeInferenceOracle::inObjectIsDenseNativeWithoutExtraIndexedProperties(HandleScript script, jsbytecode *pc)
{
    // Check whether the object is a native and index is int32 or double.
    StackTypeSet *id = script->analysis()->poppedTypes(pc, 1);
    StackTypeSet *obj = script->analysis()->poppedTypes(pc, 0);

    JSValueType idType = id->getKnownTypeTag();
    if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
        return false;

    Class *clasp = obj->getKnownClass();
    if (!clasp || !clasp->isNative())
        return false;

    return !types::TypeCanHaveExtraIndexedProperties(cx, obj);
}
Example #9
0
bool
TypeInferenceOracle::elementWriteIsDenseArray(HandleScript script, jsbytecode *pc)
{
    // Check whether the object is a dense array and index is int32 or double.
    StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2);
    StackTypeSet *id = script->analysis()->poppedTypes(pc, 1);

    JSValueType objType = obj->getKnownTypeTag();
    if (objType != JSVAL_TYPE_OBJECT)
        return false;

    JSValueType idType = id->getKnownTypeTag();
    if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
        return false;

    return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY);
}
bool
TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode *pc)
{
    // Check whether the object is a dense array and index is int32 or double.
    StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2);
    StackTypeSet *id = script->analysis()->poppedTypes(pc, 1);

    JSValueType idType = id->getKnownTypeTag();
    if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
        return false;

    Class *clasp = obj->getKnownClass();
    if (!clasp || !clasp->isNative())
        return false;

    return obj->convertDoubleElements(cx) != StackTypeSet::AmbiguousDoubleConversion;
}
Example #11
0
JS_SetSingleStepMode(JSContext *cx, HandleScript script, bool singleStep)
{
    assertSameCompartment(cx, script);

    if (!CheckDebugMode(cx))
        return false;

    return script->setStepModeFlag(cx, singleStep);
}
Example #12
0
void
C1Spewer::beginFunction(MIRGraph *graph, HandleScript script)
{
    if (!spewout_)
        return;

    this->graph  = graph;

    fprintf(spewout_, "begin_compilation\n");
    if (script) {
        fprintf(spewout_, "  name \"%s:%d\"\n", script->filename(), (int)script->lineno());
        fprintf(spewout_, "  method \"%s:%d\"\n", script->filename(), (int)script->lineno());
    } else {
        fprintf(spewout_, "  name \"asm.js compilation\"\n");
        fprintf(spewout_, "  method \"asm.js compilation\"\n");
    }
    fprintf(spewout_, "  date %d\n", (int)time(nullptr));
    fprintf(spewout_, "end_compilation\n");
}
bool
TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc)
{
    JS_ASSERT(types::IsInlinableCall(pc));

    JSOp op = JSOp(*pc);
    Bytecode *code = caller->analysis()->maybeCode(pc);

    // For foo.apply(this, arguments), the caller is foo and not the js_fun_apply function.
    // Ignore code->monitoredTypes, as we know the caller is foo
    if (op != JSOP_FUNAPPLY && code->monitoredTypes)
        return false;

    // Gets removed in Bug 796114
    if (caller->analysis()->typeBarriers(cx, pc))
        return false;

    return true;
}
Example #14
0
JS_SetTrap(JSContext *cx, HandleScript script, jsbytecode *pc, JSTrapHandler handler,
           HandleValue closure)
{
    assertSameCompartment(cx, script, closure);

    if (!CheckDebugMode(cx))
        return false;

    BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc);
    if (!site)
        return false;
    site->setTrap(cx->runtime()->defaultFreeOp(), handler, closure);
    return true;
}
Example #15
0
js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScript scriptArg,
                                  MutableHandleObject scopeArg)
{
    CHECK_REQUEST(cx);
    assertSameCompartment(cx, global);
    MOZ_ASSERT(global->is<GlobalObject>());
    MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope());

    RootedScript script(cx, scriptArg);
    Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>());
    if (script->compartment() != cx->compartment()) {
        Rooted<StaticScope*> staticScope(cx, &globalRoot->lexicalScope().staticBlock());
        staticScope = StaticNonSyntacticScope::create(cx, staticScope);
        if (!staticScope)
            return false;
        script = CloneGlobalScript(cx, staticScope, script);
        if (!script)
            return false;

        Debugger::onNewScript(cx, script);
    }

    Rooted<ClonedBlockObject*> globalLexical(cx, &globalRoot->lexicalScope());
    Rooted<ScopeObject*> scope(cx, NonSyntacticVariablesObject::create(cx, globalLexical));
    if (!scope)
        return false;

    // Unlike the non-syntactic scope chain API used by the subscript loader,
    // this API creates a fresh block scope each time.
    Rooted<StaticNonSyntacticScope*> enclosingStaticScope(cx,
        &script->enclosingStaticScope()->as<StaticNonSyntacticScope>());
    scope = ClonedBlockObject::createNonSyntactic(cx, enclosingStaticScope, scope);
    if (!scope)
        return false;

    RootedValue rval(cx);
    if (!ExecuteKernel(cx, script, *scope, UndefinedValue(),
                       NullFramePtr() /* evalInFrame */, rval.address()))
    {
        return false;
    }

    scopeArg.set(scope);
    return true;
}
BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, TempAllocator &alloc, HandleScript script)
  : cx(cx),
    script(cx, script),
    pc(script->code()),
    ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, false)),
    ionOSRCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, true)),
    debugMode_(cx->compartment()->debugMode()),
    alloc_(alloc),
    analysis_(alloc, script),
    frame(cx, script, masm),
    stubSpace_(),
    icEntries_(),
    pcMappingEntries_(),
    icLoadLabels_(),
    pushedBeforeCall_(0),
    inCall_(false),
    spsPushToggleOffset_()
{ }
Example #17
0
void
jit::IonSpewNewFunction(MIRGraph *graph, HandleScript func)
{
    if (GetIonContext()->runtime->onMainThread()) {
        ionspewer.beginFunction(graph, func);
        return;
    }

    if (!IonSpewEnabled(IonSpew_Logs))
        return;

    // Ionspewer isn't threads-safe. Therefore logging is disabled for
    // off-thread spewing. Throw informative message when trying.
    if (func) {
        IonSpew(IonSpew_Logs, "Can't log script %s:%d. (Compiled on background thread.)",
                              func->filename(), func->lineno);
    } else {
        IonSpew(IonSpew_Logs, "Can't log asm.js compilation. (Compiled on background thread.)");
    }
}
Example #18
0
js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScript scriptArg,
                                  MutableHandleObject scopeArg)
{
    CHECK_REQUEST(cx);
    assertSameCompartment(cx, global);
    MOZ_ASSERT(global->is<GlobalObject>());
    MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope());

    RootedScript script(cx, scriptArg);
    if (script->compartment() != cx->compartment()) {
        Rooted<ScopeObject*> staticScope(cx, StaticNonSyntacticScopeObjects::create(cx, nullptr));
        if (!staticScope)
            return false;
        script = CloneGlobalScript(cx, staticScope, script);
        if (!script)
            return false;

        Debugger::onNewScript(cx, script);
    }

    Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>());
    Rooted<ScopeObject*> scope(cx, NonSyntacticVariablesObject::create(cx, globalRoot));
    if (!scope)
        return false;

    JSObject* thisobj = GetThisObject(cx, global);
    if (!thisobj)
        return false;

    RootedValue thisv(cx, ObjectValue(*thisobj));
    RootedValue rval(cx);
    if (!ExecuteKernel(cx, script, *scope, thisv, UndefinedValue(), EXECUTE_GLOBAL,
                       NullFramePtr() /* evalInFrame */, rval.address()))
    {
        return false;
    }

    scopeArg.set(scope);
    return true;
}
Example #19
0
RawScript
frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
                        HandleScript evalCaller,
                        const CompileOptions &options,
                        const jschar *chars, size_t length,
                        JSString *source_ /* = NULL */,
                        unsigned staticLevel /* = 0 */,
                        SourceCompressionToken *extraSct /* = NULL */)
{
    RootedString source(cx, source_);

    /*
     * The scripted callerFrame can only be given for compile-and-go scripts
     * and non-zero static level requires callerFrame.
     */
    JS_ASSERT_IF(evalCaller, options.compileAndGo);
    JS_ASSERT_IF(staticLevel != 0, evalCaller);

    if (!CheckLength(cx, length))
        return NULL;
    JS_ASSERT_IF(staticLevel != 0, options.sourcePolicy != CompileOptions::LAZY_SOURCE);
    ScriptSource *ss = cx->new_<ScriptSource>();
    if (!ss)
        return NULL;
    if (options.filename && !ss->setFilename(cx, options.filename))
        return NULL;
    ScriptSourceHolder ssh(ss);
    SourceCompressionToken mysct(cx);
    SourceCompressionToken *sct = (extraSct) ? extraSct : &mysct;
    switch (options.sourcePolicy) {
      case CompileOptions::SAVE_SOURCE:
        if (!ss->setSourceCopy(cx, chars, length, false, sct))
            return NULL;
        break;
      case CompileOptions::LAZY_SOURCE:
        ss->setSourceRetrievable();
        break;
      case CompileOptions::NO_SOURCE:
        break;
    }

    Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true);
    if (!parser.init())
        return NULL;
    parser.sct = sct;

    GlobalSharedContext globalsc(cx, scopeChain, StrictModeFromContext(cx));

    ParseContext<FullParseHandler> pc(&parser, NULL, &globalsc, staticLevel, /* bodyid = */ 0);
    if (!pc.init())
        return NULL;

    bool savedCallerFun =
        options.compileAndGo &&
        evalCaller &&
        (evalCaller->function() || evalCaller->savedCallerFun);
    Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun,
                                                  options, staticLevel, ss, 0, length));
    if (!script)
        return NULL;

    // Global/eval script bindings are always empty (all names are added to the
    // scope dynamically via JSOP_DEFFUN/VAR).
    InternalHandle<Bindings*> bindings(script, &script->bindings);
    if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, NULL))
        return NULL;

    // We can specialize a bit for the given scope chain if that scope chain is the global object.
    JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? (JSObject*) scopeChain : NULL;
    JS_ASSERT_IF(globalScope, globalScope->isNative());
    JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass()));

    BytecodeEmitter bce(/* parent = */ NULL, &parser, &globalsc, script, evalCaller, !!globalScope,
                        options.lineno, options.selfHostingMode);
    if (!bce.init())
        return NULL;

    /* If this is a direct call to eval, inherit the caller's strictness.  */
    if (evalCaller && evalCaller->strict)
        globalsc.strict = true;

    if (options.compileAndGo) {
        if (source) {
            /*
             * Save eval program source in script->atoms[0] for the
             * eval cache (see EvalCacheLookup in jsobj.cpp).
             */
            JSAtom *atom = AtomizeString<CanGC>(cx, source);
            jsatomid _;
            if (!atom || !bce.makeAtomIndex(atom, &_))
                return NULL;
        }

        if (evalCaller && evalCaller->functionOrCallerFunction()) {
            /*
             * An eval script in a caller frame needs to have its enclosing
             * function captured in case it refers to an upvar, and someone
             * wishes to decompile it while it's running.
             */
            JSFunction *fun = evalCaller->functionOrCallerFunction();
            ObjectBox *funbox = parser.newFunctionBox(fun, &pc, fun->strict());
            if (!funbox)
                return NULL;
            bce.objectList.add(funbox);
        }
    }

    bool canHaveDirectives = true;
    for (;;) {
        TokenKind tt = parser.tokenStream.peekToken(TSF_OPERAND);
        if (tt <= TOK_EOF) {
            if (tt == TOK_EOF)
                break;
            JS_ASSERT(tt == TOK_ERROR);
            return NULL;
        }

        ParseNode *pn = parser.statement();
        if (!pn)
            return NULL;

        if (canHaveDirectives) {
            if (!parser.maybeParseDirective(pn, &canHaveDirectives))
                return NULL;
        }

        if (!FoldConstants(cx, &pn, &parser))
            return NULL;
        if (!NameFunctions(cx, pn))
            return NULL;

        if (!EmitTree(cx, &bce, pn))
            return NULL;

        parser.handler.freeTree(pn);
    }

    if (!SetSourceMap(cx, parser.tokenStream, ss, script))
        return NULL;

    if (evalCaller && evalCaller->functionOrCallerFunction()) {
        // Watch for uses of 'arguments' within the evaluated script, both as
        // free variables and as variables redeclared with 'var'.
        RootedFunction fun(cx, evalCaller->functionOrCallerFunction());
        HandlePropertyName arguments = cx->names().arguments;
        for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) {
            if (r.front().key() == arguments) {
                if (!CheckArgumentsWithinEval(cx, parser, fun))
                    return NULL;
            }
        }
        for (AtomDefnListMap::Range r = pc.decls().all(); !r.empty(); r.popFront()) {
            if (r.front().key() == arguments) {
                if (!CheckArgumentsWithinEval(cx, parser, fun))
                    return NULL;
            }
        }

        // If the eval'ed script contains any debugger statement, force construction
        // of arguments objects for the caller script and any other scripts it is
        // transitively nested inside.
        if (pc.sc->hasDebuggerStatement()) {
            RootedObject scope(cx, scopeChain);
            while (scope->isScope() || scope->isDebugScope()) {
                if (scope->isCall() && !scope->asCall().isForEval()) {
                    RootedScript script(cx, scope->asCall().callee().nonLazyScript());
                    if (script->argumentsHasVarBinding()) {
                        if (!JSScript::argumentsOptimizationFailed(cx, script))
                            return NULL;
                    }
                }
                scope = scope->enclosingScope();
            }
        }
    }

    /*
     * Nowadays the threaded interpreter needs a stop instruction, so we
     * do have to emit that here.
     */
    if (Emit1(cx, &bce, JSOP_STOP) < 0)
        return NULL;

    if (!JSScript::fullyInitFromEmitter(cx, script, &bce))
        return NULL;

    bce.tellDebuggerAboutCompiledScript(cx);

    if (sct == &mysct && !sct->complete())
        return NULL;

    return script;
}
Example #20
0
void
InterpreterFrame::initExecuteFrame(JSContext *cx, HandleScript script, AbstractFramePtr evalInFramePrev,
                                   const Value &thisv, HandleObject scopeChain, ExecuteType type)
{
    /*
     * See encoding of ExecuteType. When GLOBAL isn't set, we are executing a
     * script in the context of another frame and the frame type is determined
     * by the context.
     */
    flags_ = type | HAS_SCOPECHAIN;

    JSObject *callee = nullptr;
    if (!(flags_ & (GLOBAL))) {
        if (evalInFramePrev) {
            MOZ_ASSERT(evalInFramePrev.isFunctionFrame() || evalInFramePrev.isGlobalFrame());
            if (evalInFramePrev.isFunctionFrame()) {
                callee = evalInFramePrev.callee();
                flags_ |= FUNCTION;
            } else {
                flags_ |= GLOBAL;
            }
        } else {
            FrameIter iter(cx);
            MOZ_ASSERT(iter.isFunctionFrame() || iter.isGlobalFrame());
            MOZ_ASSERT(!iter.isAsmJS());
            if (iter.isFunctionFrame()) {
                callee = iter.callee(cx);
                flags_ |= FUNCTION;
            } else {
                flags_ |= GLOBAL;
            }
        }
    }

    Value *dstvp = (Value *)this - 2;
    dstvp[1] = thisv;

    if (isFunctionFrame()) {
        dstvp[0] = ObjectValue(*callee);
        exec.fun = &callee->as<JSFunction>();
        u.evalScript = script;
    } else {
        MOZ_ASSERT(isGlobalFrame());
        dstvp[0] = NullValue();
        exec.script = script;
#ifdef DEBUG
        u.evalScript = (JSScript *)0xbad;
#endif
    }

    scopeChain_ = scopeChain.get();
    prev_ = nullptr;
    prevpc_ = nullptr;
    prevsp_ = nullptr;

    MOZ_ASSERT_IF(evalInFramePrev, isDebuggerEvalFrame());
    evalInFramePrev_ = evalInFramePrev;

    if (script->isDebuggee())
        setIsDebuggee();

#ifdef DEBUG
    Debug_SetValueRangeToCrashOnTouch(&rval_, 1);
#endif
}
Example #21
0
bool
js::DirectEvalStringFromIon(JSContext* cx,
                            HandleObject scopeobj, HandleScript callerScript,
                            HandleValue thisValue, HandleValue newTargetValue,
                            HandleString str, jsbytecode* pc, MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeobj);

    Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global());
    if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL);
        return false;
    }

    // ES5 15.1.2.1 steps 2-8.

    unsigned staticLevel = callerScript->staticLevel() + 1;

    RootedLinearString linearStr(cx, str->ensureLinear(cx));
    if (!linearStr)
        return false;

    EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    esg.lookupInEvalCache(linearStr, callerScript, pc);

    if (!esg.foundScript()) {
        RootedScript maybeScript(cx);
        const char* filename;
        unsigned lineno;
        bool mutedErrors;
        uint32_t pcOffset;
        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                             &mutedErrors, CALLED_FROM_JSOP_EVAL);

        const char* introducerFilename = filename;
        if (maybeScript && maybeScript->scriptSource()->introducerFilename())
            introducerFilename = maybeScript->scriptSource()->introducerFilename();

        RootedObject enclosing(cx, callerScript->innermostStaticScope(pc));
        Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosing));
        if (!staticScope)
            return false;

        CompileOptions options(cx);
        options.setFileAndLine(filename, 1)
               .setIsRunOnce(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setMutedErrors(mutedErrors)
               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
               .maybeMakeStrictMode(IsStrictEvalPC(pc));

        AutoStableStringChars linearChars(cx);
        if (!linearChars.initTwoByte(cx, linearStr))
            return false;

        const char16_t* chars = linearChars.twoByteRange().start().get();
        SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller()
                                                  ? SourceBufferHolder::GiveOwnership
                                                  : SourceBufferHolder::NoOwnership;
        SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
        JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     scopeobj, staticScope, callerScript,
                                                     options, srcBuf, linearStr, staticLevel);
        if (!compiled)
            return false;

        if (compiled->strict())
            staticScope->setStrict();

        esg.setNewScript(compiled);
    }

    // Primitive 'this' values should have been filtered out by Ion. If boxed,
    // the calling frame cannot be updated to store the new object.
    MOZ_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());

    // When eval'ing strict code in a non-strict context, compute the 'this'
    // value to use from what the caller passed in. This isn't necessary if
    // the callee is not strict, as it will compute the non-strict 'this'
    // value as necessary while it executes.
    RootedValue nthisValue(cx, thisValue);
    if (!callerScript->strict() && esg.script()->strict() && !thisValue.isObject()) {
        JSObject* obj = BoxNonStrictThis(cx, thisValue);
        if (!obj)
            return false;
        nthisValue = ObjectValue(*obj);
    }

    return ExecuteKernel(cx, esg.script(), *scopeobj, nthisValue, newTargetValue,
                         ExecuteType(DIRECT_EVAL), NullFramePtr() /* evalInFrame */, vp.address());
}
Example #22
0
bool
TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode *pc)
{
    return elementWriteIsDenseNative(script->analysis()->poppedTypes(pc, 2),
                                     script->analysis()->poppedTypes(pc, 1));
}
Example #23
0
bool
SPSExit(JSContext *cx, HandleScript script)
{
    cx->runtime()->spsProfiler.exit(script, script->functionNonDelazifying());
    return true;
}
Example #24
0
bool
SPSExit(JSContext *cx, HandleScript script)
{
    cx->runtime->spsProfiler.exit(cx, script, script->function());
    return true;
}
Example #25
0
bool
SPSEnter(JSContext *cx, HandleScript script)
{
    return cx->runtime->spsProfiler.enter(cx, script, script->function());
}
Example #26
0
void
ModuleObject::init(HandleScript script)
{
    MOZ_ASSERT(!script->enclosingStaticScope());
    initReservedSlot(ScriptSlot, PrivateValue(script));
}
Example #27
0
bool
SPSEnter(JSContext *cx, HandleScript script)
{
    return cx->runtime()->spsProfiler.enter(script, script->functionNonDelazifying());
}
Example #28
0
bool
js::DirectEvalFromIon(JSContext *cx,
                      HandleObject scopeobj, HandleScript callerScript,
                      HandleValue thisValue, HandleString str,
                      MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeobj);

    Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global());
    if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
        return false;
    }

    // ES5 15.1.2.1 steps 2-8.

    unsigned staticLevel = callerScript->staticLevel + 1;

    Rooted<JSStableString*> stableStr(cx, str->ensureStable(cx));
    if (!stableStr)
        return false;

    StableCharPtr chars = stableStr->chars();
    size_t length = stableStr->length();

    EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    // Ion will not perform cross compartment direct eval calls.
    JSPrincipals *principals = cx->compartment->principals;

    esg.lookupInEvalCache(stableStr, callerScript->function(), staticLevel);

    if (!esg.foundScript()) {
        unsigned lineno;
        const char *filename;
        JSPrincipals *originPrincipals;
        CurrentScriptFileLineOrigin(cx, &filename, &lineno, &originPrincipals,
                                    CALLED_FROM_JSOP_EVAL);

        CompileOptions options(cx);
        options.setFileAndLine(filename, lineno)
               .setCompileAndGo(true)
               .setNoScriptRval(false)
               .setPrincipals(principals)
               .setOriginPrincipals(originPrincipals);
        UnrootedScript compiled = frontend::CompileScript(cx, scopeobj, callerScript, options,
                                                          chars.get(), length, stableStr, staticLevel);
        if (!compiled)
            return false;

        esg.setNewScript(compiled);
    }

    // Primitive 'this' values should have been filtered out by Ion. If boxed,
    // the calling frame cannot be updated to store the new object.
    JS_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());

    return ExecuteKernel(cx, esg.script(), *scopeobj, thisValue, ExecuteType(DIRECT_EVAL),
                         NullFramePtr() /* evalInFrame */, vp.address());
}
Example #29
0
bool
js::DirectEvalStringFromIon(JSContext *cx,
                            HandleObject scopeobj, HandleScript callerScript,
                            HandleValue thisValue, HandleString str,
                            jsbytecode *pc, MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeobj);

    Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global());
    if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL);
        return false;
    }

    // ES5 15.1.2.1 steps 2-8.

    unsigned staticLevel = callerScript->staticLevel() + 1;

    Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
    if (!flatStr)
        return false;

    EvalJSONResult ejr = TryEvalJSON(cx, callerScript, flatStr, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    esg.lookupInEvalCache(flatStr, callerScript, pc);

    if (!esg.foundScript()) {
        RootedScript maybeScript(cx);
        const char *filename;
        unsigned lineno;
        JSPrincipals *originPrincipals;
        uint32_t pcOffset;
        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                              &originPrincipals, CALLED_FROM_JSOP_EVAL);

        const char *introducerFilename = filename;
        if (maybeScript && maybeScript->scriptSource()->introducerFilename())
            introducerFilename = maybeScript->scriptSource()->introducerFilename();

        CompileOptions options(cx);
        options.setFileAndLine(filename, 1)
               .setCompileAndGo(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setOriginPrincipals(originPrincipals)
               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);

        AutoStableStringChars flatChars(cx);
        if (!flatChars.initTwoByte(cx, flatStr))
            return false;

        const char16_t *chars = flatChars.twoByteRange().start().get();
        SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller()
                                                  ? SourceBufferHolder::GiveOwnership
                                                  : SourceBufferHolder::NoOwnership;
        SourceBufferHolder srcBuf(chars, flatStr->length(), ownership);
        JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     scopeobj, callerScript, options,
                                                     srcBuf, flatStr, staticLevel);
        if (!compiled)
            return false;

        esg.setNewScript(compiled);
    }

    // Primitive 'this' values should have been filtered out by Ion. If boxed,
    // the calling frame cannot be updated to store the new object.
    JS_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());

    return ExecuteKernel(cx, esg.script(), *scopeobj, thisValue, ExecuteType(DIRECT_EVAL),
                         NullFramePtr() /* evalInFrame */, vp.address());
}
Example #30
0
bool
js::DirectEvalStringFromIon(JSContext* cx,
                            HandleObject scopeObj, HandleScript callerScript,
                            HandleValue newTargetValue, HandleString str,
                            jsbytecode* pc, MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeObj);

    Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeObj->global());
    if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL);
        return false;
    }

    // ES5 15.1.2.1 steps 2-8.

    RootedLinearString linearStr(cx, str->ensureLinear(cx));
    if (!linearStr)
        return false;

    EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    esg.lookupInEvalCache(linearStr, callerScript, pc);

    if (!esg.foundScript()) {
        RootedScript maybeScript(cx);
        const char* filename;
        unsigned lineno;
        bool mutedErrors;
        uint32_t pcOffset;
        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                             &mutedErrors, CALLED_FROM_JSOP_EVAL);

        const char* introducerFilename = filename;
        if (maybeScript && maybeScript->scriptSource()->introducerFilename())
            introducerFilename = maybeScript->scriptSource()->introducerFilename();

        RootedObject enclosing(cx, callerScript->innermostStaticScope(pc));
        Rooted<StaticEvalScope*> staticScope(cx, StaticEvalScope::create(cx, enclosing));
        if (!staticScope)
            return false;

        CompileOptions options(cx);
        options.setIsRunOnce(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setMutedErrors(mutedErrors)
               .maybeMakeStrictMode(IsStrictEvalPC(pc));

        if (introducerFilename) {
            options.setFileAndLine(filename, 1);
            options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
        } else {
            options.setFileAndLine("eval", 1);
            options.setIntroductionType("eval");
        }

        AutoStableStringChars linearChars(cx);
        if (!linearChars.initTwoByte(cx, linearStr))
            return false;

        const char16_t* chars = linearChars.twoByteRange().start().get();
        SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller()
                                                  ? SourceBufferHolder::GiveOwnership
                                                  : SourceBufferHolder::NoOwnership;
        SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
        JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     scopeObj, staticScope, callerScript,
                                                     options, srcBuf, linearStr);
        if (!compiled)
            return false;

        if (compiled->strict())
            staticScope->setStrict();

        esg.setNewScript(compiled);
    }

    return ExecuteKernel(cx, esg.script(), *scopeObj, newTargetValue,
                         NullFramePtr() /* evalInFrame */, vp.address());
}