Beispiel #1
0
static UnrootedScript
GetBailedJSScript(JSContext *cx)
{
    AutoAssertNoGC nogc;

    // Just after the frame conversion, we can safely interpret the ionTop as JS
    // frame because it targets the bailed JS frame converted to an exit frame.
    IonJSFrameLayout *frame = reinterpret_cast<IonJSFrameLayout*>(cx->runtime->ionTop);
    switch (GetCalleeTokenTag(frame->calleeToken())) {
      case CalleeToken_Function: {
        JSFunction *fun = CalleeTokenToFunction(frame->calleeToken());
        return fun->nonLazyScript();
      }
      case CalleeToken_Script:
        return CalleeTokenToScript(frame->calleeToken());
      default:
        JS_NOT_REACHED("unexpected callee token kind");
        return NULL;
    }
}
Beispiel #2
0
bool
CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval)
{
    rval.set(MagicValue(JS_IS_CONSTRUCTING));

    if (callee->is<JSFunction>()) {
        JSFunction *fun = &callee->as<JSFunction>();
        if (fun->isInterpretedConstructor()) {
            JSScript *script = fun->getOrCreateScript(cx);
            if (!script || !script->ensureHasTypes(cx))
                return false;
            JSObject *thisObj = CreateThisForFunction(cx, callee, GenericObject);
            if (!thisObj)
                return false;
            rval.set(ObjectValue(*thisObj));
        }
    }

    return true;
}
AsmJSActivation::AsmJSActivation(JSContext *cx, const AsmJSModule &module, unsigned entryIndex)
  : cx_(cx),
    module_(module),
    entryIndex_(entryIndex),
    errorRejoinSP_(NULL),
    profiler_(NULL),
    resumePC_(NULL)
{
    if (cx->runtime->spsProfiler.enabled()) {
        profiler_ = &cx->runtime->spsProfiler;
        JSFunction *fun = module_.exportedFunction(entryIndex_).unclonedFunObj();
        profiler_->enter(cx_, fun->nonLazyScript(), fun);
    }

    prev_ = cx_->runtime->mainThread.asmJSActivationStack_;

    PerThreadData::AsmJSActivationStackLock lock(cx_->runtime->mainThread);
    cx_->runtime->mainThread.asmJSActivationStack_ = this;

    (void) errorRejoinSP_;  // squelch GCC warning
}
Beispiel #4
0
static JSFunction*
NewExportedFunction(JSContext* cx, Handle<WasmModuleObject*> moduleObj, const ExportMap& exportMap,
                    uint32_t exportIndex)
{
    unsigned numArgs = moduleObj->module().exports()[exportIndex].sig().args().length();

    const char* chars = exportMap.exportNames[exportIndex].get();
    RootedAtom name(cx, AtomizeUTF8Chars(cx, chars, strlen(chars)));
    if (!name)
        return nullptr;

    JSFunction* fun = NewNativeConstructor(cx, WasmCall, numArgs, name,
                                           gc::AllocKind::FUNCTION_EXTENDED, GenericObject,
                                           JSFunction::ASMJS_CTOR);
    if (!fun)
        return nullptr;

    fun->setExtendedSlot(FunctionExtended::WASM_MODULE_SLOT, ObjectValue(*moduleObj));
    fun->setExtendedSlot(FunctionExtended::WASM_EXPORT_INDEX_SLOT, Int32Value(exportIndex));
    return fun;
}
JSValue JSInjectedScriptHost::evaluate(ExecState* exec)
{
    JSValue expression = exec->argument(0);
    if (!expression.isString())
        return throwError(exec, createError(exec, "String argument expected."));
    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    JSFunction* evalFunction = globalObject->evalFunction();
    CallData callData;
    CallType callType = evalFunction->methodTable()->getCallData(evalFunction, callData);
    if (callType == CallTypeNone)
        return jsUndefined();
    MarkedArgumentBuffer args;
    args.append(expression);

    bool wasEvalEnabled = globalObject->evalEnabled();
    globalObject->setEvalEnabled(true);
    JSValue result = JSC::call(exec, evalFunction, callType, callData, exec->globalThisValue(), args);
    globalObject->setEvalEnabled(wasEvalEnabled);

    return result;
}
Beispiel #6
0
bool
GlobalObject::getSelfHostedFunction(JSContext* cx, HandleAtom selfHostedName, HandleAtom name,
                                    unsigned nargs, MutableHandleValue funVal)
{
    RootedId shId(cx, AtomToId(selfHostedName));
    RootedObject holder(cx, cx->global()->intrinsicsHolder());

    if (cx->global()->maybeGetIntrinsicValue(shId, funVal.address()))
        return true;

    JSFunction* fun =
        NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
                            name, JSFunction::ExtendedFinalizeKind, SingletonObject);
    if (!fun)
        return false;
    fun->setIsSelfHostedBuiltin();
    fun->setExtendedSlot(0, StringValue(selfHostedName));
    funVal.setObject(*fun);

    return cx->global()->addIntrinsicValue(cx, shId, funVal);
}
JSBool
CallObject::setArgOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
    CallObject &callobj = obj->asCall();
    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
    unsigned i = (uint16_t) JSID_TO_INT(id);

    if (StackFrame *fp = callobj.maybeStackFrame())
        fp->formalArg(i) = *vp;
    else
        callobj.setArg(i, *vp);

    JSFunction *fun = callobj.getCalleeFunction();
    JSScript *script = fun->script();
    if (!script->ensureHasTypes(cx))
        return false;

    TypeScript::SetArgument(cx, script, i, *vp);

    return true;
}
Beispiel #8
0
inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
{
    ExecState* exec = execCallee->callerFrame();
    JSValue calleeAsValue = execCallee->calleeAsValue();
    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (UNLIKELY(!calleeAsFunctionCell))
        return handleHostCall(execCallee, calleeAsValue, kind);
    
    JSFunction* function = asFunction(calleeAsFunctionCell);
    execCallee->setScopeChain(function->scopeUnchecked());
    ExecutableBase* executable = function->executable();
    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
        if (error) {
            exec->globalData().exception = error;
            return 0;
        }
    }
    return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
}
Beispiel #9
0
static bool
CreateLazyScriptsForCompartment(JSContext* cx)
{
    AutoObjectVector lazyFunctions(cx);

    // Find all live root lazy functions in the compartment: those which
    // have not been compiled, which have a source object, indicating that
    // they have a parent, and which do not have an uncompiled enclosing
    // script. The last condition is so that we don't compile lazy scripts
    // whose enclosing scripts failed to compile, indicating that the lazy
    // script did not escape the script.
    //
    // Note that while we ideally iterate over LazyScripts, LazyScripts do not
    // currently stand in 1-1 relation with JSScripts; JSFunctions with the
    // same LazyScript may create different JSScripts due to relazification of
    // clones. See bug 1105306.
    for (gc::ZoneCellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
        JSObject* obj = i.get<JSObject>();
        if (obj->compartment() == cx->compartment() && obj->is<JSFunction>()) {
            JSFunction* fun = &obj->as<JSFunction>();
            if (fun->isInterpretedLazy()) {
                LazyScript* lazy = fun->lazyScriptOrNull();
                if (lazy && lazy->sourceObject() && !lazy->maybeScript() &&
                    !lazy->hasUncompiledEnclosingScript())
                {
                    if (!lazyFunctions.append(fun))
                        return false;
                }
            }
        }
    }

    // Create scripts for each lazy function, updating the list of functions to
    // process with any newly exposed inner functions in created scripts.
    // A function cannot be delazified until its outer script exists.
    for (size_t i = 0; i < lazyFunctions.length(); i++) {
        JSFunction* fun = &lazyFunctions[i]->as<JSFunction>();

        // lazyFunctions may have been populated with multiple functions for
        // a lazy script.
        if (!fun->isInterpretedLazy())
            continue;

        LazyScript* lazy = fun->lazyScript();
        bool lazyScriptHadNoScript = !lazy->maybeScript();

        JSScript* script = fun->getOrCreateScript(cx);
        if (!script)
            return false;
        if (lazyScriptHadNoScript && !AddInnerLazyFunctionsFromScript(script, lazyFunctions))
            return false;
    }

    return true;
}
Beispiel #10
0
static JSFunction*
NewExportedFunction(JSContext* cx, HandleWasmInstanceObject instanceObj, uint32_t funcExportIndex)
{
    Instance& instance = instanceObj->instance();
    const Metadata& metadata = instance.metadata();
    const FuncExport& fe = metadata.funcExports[funcExportIndex];
    unsigned numArgs = fe.sig().args().length();

    RootedAtom name(cx, instance.getFuncAtom(cx, fe.funcIndex()));
    if (!name)
        return nullptr;

    JSFunction* fun = NewNativeConstructor(cx, WasmCall, numArgs, name,
                                           gc::AllocKind::FUNCTION_EXTENDED, GenericObject,
                                           JSFunction::ASMJS_CTOR);
    if (!fun)
        return nullptr;

    fun->setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT, ObjectValue(*instanceObj));
    fun->setExtendedSlot(FunctionExtended::WASM_EXPORT_INDEX_SLOT, Int32Value(funcExportIndex));
    return fun;
}
Beispiel #11
0
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
{
    JSValue thisValue = exec->thisValue();
    if (thisValue.inherits(JSFunction::info())) {
        JSFunction* function = jsCast<JSFunction*>(thisValue);
        if (function->isHostOrBuiltinFunction())
            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));

        FunctionExecutable* executable = function->jsExecutable();
        String source = executable->source().provider()->getRange(
            executable->parametersStartOffset(),
            executable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), source));
    }

    if (thisValue.inherits(InternalFunction::info())) {
        InternalFunction* function = asInternalFunction(thisValue);
        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
    }

    return throwVMTypeError(exec);
}
Beispiel #12
0
inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
{
    ExecState* exec = execCallee->callerFrame();
    VM* vm = &exec->vm();
    NativeCallFrameTracer tracer(vm, exec);
    
    JSValue calleeAsValue = execCallee->calleeAsValue();
    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (!calleeAsFunctionCell)
        return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));

    JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
    execCallee->setScope(callee->scopeUnchecked());
    ExecutableBase* executable = callee->executable();

    MacroAssemblerCodePtr codePtr;
    CodeBlock* codeBlock = 0;
    if (executable->isHostFunction())
        codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
    else {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind);
        if (error) {
            vm->throwException(exec, createStackOverflowError(exec));
            return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
        }
        codeBlock = functionExecutable->codeBlockFor(kind);
        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
        else
            codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
    }
    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
    if (!callLinkInfo.seenOnce())
        callLinkInfo.setSeen();
    else
        linkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
    return reinterpret_cast<char*>(codePtr.executableAddress());
}
Beispiel #13
0
/*
 * This function must only be called after the early prologue, since it depends
 * on fp->exec.fun.
 */
void * JS_FASTCALL
stubs::FixupArity(VMFrame &f, uint32 nactual)
{
    JSContext *cx = f.cx;
    StackFrame *oldfp = f.fp();

    JS_ASSERT(nactual != oldfp->numFormalArgs());

    /*
     * Grossssss! *move* the stack frame. If this ends up being perf-critical,
     * we can figure out how to spot-optimize it. Be careful to touch only the
     * members that have been initialized by initJitFrameCallerHalf and the
     * early prologue.
     */
    MaybeConstruct construct = oldfp->isConstructing();
    JSFunction *fun          = oldfp->fun();
    JSScript *script         = fun->script();
    void *ncode              = oldfp->nativeReturnAddress();

    /* Pop the inline frame. */
    f.regs.popPartialFrame((Value *)oldfp);

    /* Reserve enough space for a callee frame. */
    CallArgs args = CallArgsFromSp(nactual, f.regs.sp);
    StackFrame *fp = cx->stack.getFixupFrame(cx, DONT_REPORT_ERROR, args, fun,
                                             script, ncode, construct, &f.stackLimit);
    if (!fp) {
        /*
         * The PC is not coherent with the current frame, so fix it up for
         * exception handling.
         */
        f.regs.pc = f.jit()->nativeToPC(ncode);
        js_ReportOverRecursed(cx);
        THROWV(NULL);
    }

    /* The caller takes care of assigning fp to regs. */
    return fp;
}
Beispiel #14
0
inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
{
    ExecState* exec = execCallee->callerFrame();
    JSGlobalData* globalData = &exec->globalData();
    NativeCallFrameTracer tracer(globalData, exec);
    
    JSValue calleeAsValue = execCallee->calleeAsValue();
    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (!calleeAsFunctionCell)
        return handleHostCall(execCallee, calleeAsValue, kind);

    JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
    execCallee->setScopeChain(callee->scopeUnchecked());
    ExecutableBase* executable = callee->executable();

    MacroAssemblerCodePtr codePtr;
    CodeBlock* codeBlock = 0;
    if (executable->isHostFunction())
        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
    else {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
        if (error) {
            globalData->exception = createStackOverflowError(exec);
            return 0;
        }
        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
        else
            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
    }
    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
    if (!callLinkInfo.seenOnce())
        callLinkInfo.setSeen();
    else
        dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
    return codePtr.executableAddress();
}
Beispiel #15
0
void StackIterator::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
{
    ASSERT(codeOrigin);
    ASSERT(!callFrame->hasHostCallFrameFlag());

    unsigned frameOffset = inlinedFrameOffset(codeOrigin);
    bool isInlined = !!frameOffset;
    if (isInlined) {
        InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame;

        m_frame.m_callFrame = callFrame;
        m_frame.m_inlineCallFrame = inlineCallFrame;
        m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
        m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock();
        m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;

        JSFunction* callee = inlineCallFrame->callee.get();
        if (callee) {
            m_frame.m_scope = callee->scope();
            m_frame.m_callee = callee;
        } else {
            CallFrame* inlinedFrame = callFrame + frameOffset;
            m_frame.m_scope = inlinedFrame->scope();
            m_frame.m_callee = inlinedFrame->callee();
        }
        ASSERT(m_frame.scope());
        ASSERT(m_frame.callee());

        // The callerFrame just needs to be non-null to indicate that we
        // haven't reached the last frame yet. Setting it to the root
        // frame (i.e. the callFrame that this inlined frame is called from)
        // would work just fine.
        m_frame.m_callerFrame = callFrame;
        return;
    }

    readNonInlinedFrame(callFrame, codeOrigin);
}
Beispiel #16
0
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    JSValue thisValue = exec->thisValue();
    if (thisValue.inherits(JSFunction::info())) {
        JSFunction* function = jsCast<JSFunction*>(thisValue);
        if (function->isHostOrBuiltinFunction()) {
            scope.release();
            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n    [native code]\n}"));
        }

        FunctionExecutable* executable = function->jsExecutable();
        if (executable->isClass()) {
            StringView classSource = executable->classSource().view();
            return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying()));
        }

        if (thisValue.inherits(JSAsyncFunction::info())) {
            String functionHeader = executable->isArrowFunction() ? "async " : "async function ";

            StringView source = executable->source().provider()->getRange(
                executable->parametersStartOffset(),
                executable->parametersStartOffset() + executable->source().length());
            return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
        }

        String functionHeader = executable->isArrowFunction() ? "" : "function ";
        
        StringView source = executable->source().provider()->getRange(
            executable->parametersStartOffset(),
            executable->parametersStartOffset() + executable->source().length());
        scope.release();
        return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
    }

    if (thisValue.inherits(InternalFunction::info())) {
        InternalFunction* function = asInternalFunction(thisValue);
        scope.release();
        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
    }

    if (thisValue.isObject()) {
        JSObject* object = asObject(thisValue);
        if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
            CallData callData;
            if (object->methodTable(vm)->getCallData(object, callData) != CallType::None) {
                if (auto* classInfo = object->classInfo()) {
                    scope.release();
                    return JSValue::encode(jsMakeNontrivialString(exec, "function ", classInfo->className, "() {\n    [native code]\n}"));
                }
            }
        }
    }

    return throwVMTypeError(exec, scope);
}
void ScriptCallStack::initialize()
{
    if (!m_caller || m_initialized)
        return;

    int signedLineNumber;
    intptr_t sourceID;
    UString urlString;
    JSValue function;
    // callFrame must exist if m_caller is not null.
    CallFrame* callFrame = m_exec->callerFrame();
    while (true) {
        ASSERT(callFrame);
        m_exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
        if (!function)
            break;
        JSFunction* jsFunction = asFunction(function);
        unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0;
        m_frames.append(ScriptCallFrame(jsFunction->name(m_exec), urlString, lineNumber, m_exec, 0));
        callFrame = callFrame->callerFrame();
    }
    m_initialized = true;
}
Beispiel #18
0
JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
    if (thisValue.inherits(&JSFunction::info)) {
        JSFunction* function = asFunction(thisValue);
        if (!function->isHostFunction()) {
            FunctionExecutable* executable = function->jsExecutable();
            UString sourceString = executable->source().toString();
            insertSemicolonIfNeeded(sourceString);
            return jsString(exec, makeString("function ", function->name(exec), "(", executable->paramString(), ") ", sourceString));
        }
    }

    if (thisValue.inherits(&InternalFunction::info)) {
        InternalFunction* function = asInternalFunction(thisValue);
        return jsString(exec, makeString("function ", function->name(exec), "() {\n    [native code]\n}"));
    }

#ifdef QT_BUILD_SCRIPT_LIB  //same error message as in the old engine, and in mozilla
    return throwError(exec, TypeError, "Function.prototype.toString called on incompatible object");
#else
    return throwError(exec, TypeError);
#endif
}
Beispiel #19
0
static void
MarkFunctionsWithinEvalScript(JSScript *script)
{
    // Mark top level functions in an eval script as being within an eval and,
    // if applicable, inside a with statement.

    if (!script->hasObjects())
        return;

    ObjectArray *objects = script->objects();
    size_t start = script->innerObjectsStart();

    for (size_t i = start; i < objects->length; i++) {
        JSObject *obj = objects->vector[i];
        if (obj->is<JSFunction>()) {
            JSFunction *fun = &obj->as<JSFunction>();
            if (fun->hasScript())
                fun->nonLazyScript()->setDirectlyInsideEval();
            else if (fun->isInterpretedLazy())
                fun->lazyScript()->setDirectlyInsideEval();
        }
    }
}
Beispiel #20
0
Shape *
PropertyTree::newShape(ExclusiveContext *cx)
{
    Shape *shape = js_NewGCShape(cx);
    JSContext *jcx = cx->asJSContext();
    jsbytecode *pc;

    JSScript *script = jcx->currentScript(&pc,JSContext::ALLOW_CROSS_COMPARTMENT);
    if (script->savedCallerFun()) {
    	JSFunction *cFunc = nullptr;
    	JSScript *cScript = nullptr;

    	if (script->savedCallerFun()) {
    		cFunc = script->getCallerFunction();
    	 	cScript = cFunc->nonLazyScript();
    	}
    }


    if (!shape)
        js_ReportOutOfMemory(cx);
    return shape;
}
Beispiel #21
0
Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
{

    VM& vm = exec->vm();
    // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame.
    // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == exec->callee()
    ASSERT(!newTarget || newTarget.isConstructor());

    if (newTarget && newTarget != exec->callee()) {
        // newTarget may be an InternalFunction if we were called from Reflect.construct.
        JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget);

        if (LIKELY(targetFunction)) {
            Structure* structure = targetFunction->rareData(vm)->internalFunctionAllocationStructure();
            if (LIKELY(structure && structure->classInfo() == baseClass->classInfo()))
                return structure;

            // Note, Reflect.construct might cause the profile to churn but we don't care.
            JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype);
            if (UNLIKELY(vm.exception()))
                return nullptr;
            if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue))
                return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
        } else {
            JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype);
            if (UNLIKELY(vm.exception()))
                return nullptr;
            if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue)) {
                // This only happens if someone Reflect.constructs our builtin constructor with another builtin constructor as the new.target.
                // Thus, we don't care about the cost of looking up the structure from our hash table every time.
                return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
            }
        }
    }
    
    return baseClass;
}
Beispiel #22
0
static bool
CreateLazyScriptsForCompartment(JSContext* cx)
{
    AutoObjectVector lazyFunctions(cx);

    if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION))
        return false;

    // Methods, for instance {get method() {}}, are extended functions that can
    // be relazified, so we need to handle those as well.
    if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION_EXTENDED))
        return false;

    // Create scripts for each lazy function, updating the list of functions to
    // process with any newly exposed inner functions in created scripts.
    // A function cannot be delazified until its outer script exists.
    for (size_t i = 0; i < lazyFunctions.length(); i++) {
        JSFunction* fun = &lazyFunctions[i]->as<JSFunction>();

        // lazyFunctions may have been populated with multiple functions for
        // a lazy script.
        if (!fun->isInterpretedLazy())
            continue;

        LazyScript* lazy = fun->lazyScript();
        bool lazyScriptHadNoScript = !lazy->maybeScript();

        JSScript* script = fun->getOrCreateScript(cx);
        if (!script)
            return false;
        if (lazyScriptHadNoScript && !AddInnerLazyFunctionsFromScript(script, lazyFunctions))
            return false;
    }

    return true;
}
Beispiel #23
0
void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
    JSFunction* thisObject = jsCast<JSFunction*>(cell);
    if (thisObject->isHostFunction()) {
        Base::put(thisObject, exec, propertyName, value, slot);
        return;
    }
    if (propertyName == exec->propertyNames().prototype) {
        // Make sure prototype has been reified, such that it can only be overwritten
        // following the rules set out in ECMA-262 8.12.9.
        PropertySlot slot;
        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
    }
    if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
        // This will trigger the property to be reified, if this is not already the case!
        bool okay = thisObject->hasProperty(exec, propertyName);
        ASSERT_UNUSED(okay, okay);
        Base::put(thisObject, exec, propertyName, value, slot);
        return;
    }
    if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
        return;
    Base::put(thisObject, exec, propertyName, value, slot);
}
EncodedJSValue JSC_HOST_CALL JSPromisePrototypeFuncCatch(ExecState* exec)
{
    JSPromise* thisObject = jsDynamicCast<JSPromise*>(exec->thisValue());
    if (!thisObject)
        return throwVMError(exec, createTypeError(exec, "Receiver of catch must be a Promise"));
    
    JSValue rejectCallback = exec->argument(0);
    if (!rejectCallback.isUndefined()) {
        CallData callData;
        CallType callType = getCallData(rejectCallback, callData);
        if (callType == CallTypeNone)
            return throwVMError(exec, createTypeError(exec, "Expected function or undefined as as first argument"));
    }

    JSFunction* callee = jsCast<JSFunction*>(exec->callee());
    JSGlobalObject* globalObject = callee->globalObject();

    // 1. Let promise be a new promise.
    JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);

    // 2. Let resolver be promise's associated resolver.
    JSPromiseResolver* resolver = promise->resolver();

    // 3. Let fulfillCallback be a new promise callback for resolver and its fulfill algorithm.
    InternalFunction* fulfillWrapper = JSPromiseCallback::create(exec, globalObject, globalObject->promiseCallbackStructure(), resolver, JSPromiseCallback::Fulfill);

    // 4. Let rejectWrapper be a promise wrapper callback for resolver and rejectCallback if rejectCallback is
    //    not omitted and a promise callback for resolver and its reject algorithm otherwise.
    InternalFunction* rejectWrapper = wrapCallback(exec, globalObject, rejectCallback, resolver, JSPromiseCallback::Reject);

    // 5. Append fulfillWrapper and rejectWrapper to the context object.
    thisObject->appendCallbacks(exec, fulfillWrapper, rejectWrapper);

    // 6. Return promise.
    return JSValue::encode(promise);
}
static bool
AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind)
{
    // Find all live root lazy functions in the compartment: those which
    // have not been compiled, which have a source object, indicating that
    // they have a parent, and which do not have an uncompiled enclosing
    // script. The last condition is so that we don't compile lazy scripts
    // whose enclosing scripts failed to compile, indicating that the lazy
    // script did not escape the script.
    for (gc::ZoneCellIter i(cx->zone(), kind); !i.done(); i.next()) {
        JSObject* obj = i.get<JSObject>();

        // Sweeping is incremental; take care to not delazify functions that
        // are about to be finalized. GC things referenced by objects that are
        // about to be finalized (e.g., in slots) may already be freed.
        if (gc::IsObjectAboutToBeFinalized(&obj) ||
            obj->compartment() != cx->compartment() ||
            !obj->is<JSFunction>())
        {
            continue;
        }

        JSFunction* fun = &obj->as<JSFunction>();
        if (fun->isInterpretedLazy()) {
            LazyScript* lazy = fun->lazyScriptOrNull();
            if (lazy && lazy->sourceObject() && !lazy->maybeScript() &&
                !lazy->hasUncompiledEnclosingScript())
            {
                if (!lazyFunctions.append(fun))
                    return false;
            }
        }
    }

    return true;
}
Beispiel #26
0
bool
SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame)
{
    if (iter.done()) {
        frame.set(nullptr);
        return true;
    }

    // Don't report the over-recursion error because if we are blowing the stack
    // here, we already blew the stack in JS, reported it, and we are creating
    // the saved stack for the over-recursion error object. We do this check
    // here, rather than inside saveCurrentStack, because in some cases we will
    // pass the check there, despite later failing the check here (for example,
    // in js/src/jit-test/tests/saved-stacks/bug-1006876-too-much-recursion.js).
    JS_CHECK_RECURSION_DONT_REPORT(cx, return false);

    ScriptFrameIter thisFrame(iter);
    Rooted<SavedFrame*> parentFrame(cx);
    if (!insertFrames(cx, ++iter, &parentFrame))
        return false;

    LocationValue location;
    if (!getLocation(cx, thisFrame.script(), thisFrame.pc(), &location))
        return false;

    JSFunction *callee = thisFrame.maybeCallee();
    SavedFrame::Lookup lookup(location.source,
                              location.line,
                              location.column,
                              callee ? callee->displayAtom() : nullptr,
                              parentFrame,
                              thisFrame.compartment()->principals);

    frame.set(getOrCreateSavedFrame(cx, lookup));
    return frame.get() != nullptr;
}
Beispiel #27
0
static bool
AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind)
{
    // Find all live root lazy functions in the compartment: those which have a
    // source object, indicating that they have a parent, and which do not have
    // an uncompiled enclosing script. The last condition is so that we don't
    // compile lazy scripts whose enclosing scripts failed to compile,
    // indicating that the lazy script did not escape the script.
    //
    // Some LazyScripts have a non-null |JSScript* script| pointer. We still
    // want to delazify in that case: this pointer is weak so the JSScript
    // could be destroyed at the next GC.

    for (auto i = cx->zone()->cellIter<JSObject>(kind); !i.done(); i.next()) {
        JSFunction* fun = &i->as<JSFunction>();

        // Sweeping is incremental; take care to not delazify functions that
        // are about to be finalized. GC things referenced by objects that are
        // about to be finalized (e.g., in slots) may already be freed.
        if (gc::IsAboutToBeFinalizedUnbarriered(&fun) ||
            fun->compartment() != cx->compartment())
        {
            continue;
        }

        if (fun->isInterpretedLazy()) {
            LazyScript* lazy = fun->lazyScriptOrNull();
            if (lazy && lazy->sourceObject() && !lazy->hasUncompiledEnclosingScript()) {
                if (!lazyFunctions.append(fun))
                    return false;
            }
        }
    }

    return true;
}
Beispiel #28
0
bool
ContextStack::pushInvokeFrame(JSContext *cx, const CallArgs &args,
                              InitialFrameFlags initial, InvokeFrameGuard *ifg)
{
    JS_ASSERT(onTop());
    JS_ASSERT(space().firstUnused() == args.end());

    JSObject &callee = args.callee();
    JSFunction *fun = callee.toFunction();
    JSScript *script = fun->script();

    StackFrame::Flags flags = ToFrameFlags(initial);
    StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, fun, script, &flags);
    if (!fp)
        return false;

    fp->initCallFrame(cx, *fun, script, args.length(), flags);
    ifg->regs_.prepareToRun(*fp, script);

    ifg->prevRegs_ = seg_->pushRegs(ifg->regs_);
    JS_ASSERT(space().firstUnused() == ifg->regs_.sp);
    ifg->setPushed(*this);
    return true;
}
Beispiel #29
0
inline char* virtualForWithFunction(ExecState* execCallee, CodeSpecializationKind kind, JSCell*& calleeAsFunctionCell)
{
    ExecState* exec = execCallee->callerFrame();
    VM* vm = &exec->vm();
    NativeCallFrameTracer tracer(vm, exec);

    JSValue calleeAsValue = execCallee->calleeAsValue();
    calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (UNLIKELY(!calleeAsFunctionCell))
        return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
    
    JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
    execCallee->setScope(function->scopeUnchecked());
    ExecutableBase* executable = function->executable();
    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->prepareForExecution(execCallee, function->scope(), kind);
        if (error) {
            exec->vm().throwException(execCallee, error);
            return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
        }
    }
    return reinterpret_cast<char*>(executable->generatedJITCodeWithArityCheckFor(kind).executableAddress());
}
Beispiel #30
0
static bool
CreateLazyScriptsForCompartment(JSContext *cx)
{
    AutoObjectVector lazyFunctions(cx);

    // Find all live lazy scripts in the compartment, and via them all root
    // lazy functions in the compartment: those which have not been compiled,
    // which have a source object, indicating that they have a parent, and
    // which do not have an uncompiled enclosing script. The last condition is
    // so that we don't compile lazy scripts whose enclosing scripts failed to
    // compile, indicating that the lazy script did not escape the script.
    for (gc::ZoneCellIter i(cx->zone(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) {
        LazyScript *lazy = i.get<LazyScript>();
        JSFunction *fun = lazy->functionNonDelazifying();
        if (fun->compartment() == cx->compartment() &&
            lazy->sourceObject() && !lazy->maybeScript() &&
            !lazy->hasUncompiledEnclosingScript())
        {
            MOZ_ASSERT(fun->isInterpretedLazy());
            MOZ_ASSERT(lazy == fun->lazyScriptOrNull());
            if (!lazyFunctions.append(fun))
                return false;
        }
    }

    // Create scripts for each lazy function, updating the list of functions to
    // process with any newly exposed inner functions in created scripts.
    // A function cannot be delazified until its outer script exists.
    for (size_t i = 0; i < lazyFunctions.length(); i++) {
        JSFunction *fun = &lazyFunctions[i]->as<JSFunction>();

        // lazyFunctions may have been populated with multiple functions for
        // a lazy script.
        if (!fun->isInterpretedLazy())
            continue;

        JSScript *script = fun->getOrCreateScript(cx);
        if (!script)
            return false;
        if (!AddInnerLazyFunctionsFromScript(script, lazyFunctions))
            return false;
    }

    return true;
}