Exemple #1
0
CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
    ConcurrentJITLocker locker(profiledBlock->m_lock);
    
    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
    if (!profiledBlock->hasBaselineJITProfiling())
        return computeFromLLInt(profiledBlock, bytecodeIndex);
    
    if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
        return CallLinkStatus::takesSlowPath();
    
    CallLinkInfo& callLinkInfo = profiledBlock->getCallLinkInfo(bytecodeIndex);
    if (callLinkInfo.stub)
        return CallLinkStatus(callLinkInfo.stub->executable(), callLinkInfo.stub->structure());
    
    JSFunction* target = callLinkInfo.lastSeenCallee.get();
    if (!target)
        return computeFromLLInt(profiledBlock, bytecodeIndex);
    
    if (callLinkInfo.hasSeenClosure)
        return CallLinkStatus(target->executable(), target->structure());

    return CallLinkStatus(target);
#else
    return CallLinkStatus();
#endif
}
CallLinkStatus CallLinkStatus::computeFromLLInt(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
#if ENABLE(LLINT)
#if ENABLE(DFG_JIT)
    if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction))) {
        // We could force this to be a closure call, but instead we'll just assume that it
        // takes slow path.
        return takesSlowPath();
    }
#else
    UNUSED_PARAM(locker);
#endif

    VM& vm = *profiledBlock->vm();

    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
    OpcodeID op = vm.interpreter->getOpcodeID(instruction[0].u.opcode);
    if (op != op_call && op != op_construct)
        return CallLinkStatus();

    LLIntCallLinkInfo* callLinkInfo = instruction[5].u.callLinkInfo;

    return CallLinkStatus(callLinkInfo->lastSeenCallee.get());
#else
    return CallLinkStatus();
#endif
}
CallLinkStatus CallLinkStatus::computeFor(const ConcurrentJITLocker&, CallLinkInfo& callLinkInfo)
{
    // Note that despite requiring that the locker is held, this code is racy with respect
    // to the CallLinkInfo: it may get cleared while this code runs! This is because
    // CallLinkInfo::unlink() may be called from a different CodeBlock than the one that owns
    // the CallLinkInfo and currently we save space by not having CallLinkInfos know who owns
    // them. So, there is no way for either the caller of CallLinkInfo::unlock() or unlock()
    // itself to figure out which lock to lock.
    //
    // Fortunately, that doesn't matter. The only things we ask of CallLinkInfo - the slow
    // path count, the stub, and the target - can all be asked racily. Stubs and targets can
    // only be deleted at next GC, so if we load a non-null one, then it must contain data
    // that is still marginally valid (i.e. the pointers ain't stale). This kind of raciness
    // is probably OK for now.

    if (callLinkInfo.slowPathCount >= Options::couldTakeSlowCaseMinimumCount())
        return takesSlowPath();

    if (ClosureCallStubRoutine* stub = callLinkInfo.stub.get())
        return CallLinkStatus(stub->executable(), stub->structure());

    JSFunction* target = callLinkInfo.lastSeenCallee.get();
    if (!target)
        return CallLinkStatus();

    if (callLinkInfo.hasSeenClosure)
        return CallLinkStatus(target->executable(), target->structure());

    return CallLinkStatus(target);
}
Exemple #4
0
CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
#if ENABLE(LLINT)
    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
    LLIntCallLinkInfo* callLinkInfo = instruction[5].u.callLinkInfo;
    
    return CallLinkStatus(callLinkInfo->lastSeenCallee.get());
#else
    return CallLinkStatus();
#endif
}
CallLinkStatus CallLinkStatus::computeFor(
    CodeBlock* profiledBlock, unsigned bytecodeIndex, const CallLinkInfoMap& map)
{
    ConcurrentJITLocker locker(profiledBlock->m_lock);

    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
    UNUSED_PARAM(map);
#if ENABLE(DFG_JIT)
    if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache))
            || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint))
            || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable)))
        return takesSlowPath();

    CallLinkInfo* callLinkInfo = map.get(CodeOrigin(bytecodeIndex));
    if (!callLinkInfo)
        return computeFromLLInt(locker, profiledBlock, bytecodeIndex);

    CallLinkStatus result = computeFor(locker, *callLinkInfo);
    if (!result)
        return computeFromLLInt(locker, profiledBlock, bytecodeIndex);

    if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction)))
        result.makeClosureCall();

    return result;
#else
    return CallLinkStatus();
#endif
}
Exemple #6
0
CallLinkStatus CallLinkStatus::computeFor(const ConcurrentJITLocker&, CallLinkInfo& callLinkInfo)
{
    if (callLinkInfo.slowPathCount >= Options::couldTakeSlowCaseMinimumCount())
        return takesSlowPath();
    
    if (callLinkInfo.stub)
        return CallLinkStatus(callLinkInfo.stub->executable(), callLinkInfo.stub->structure());
    
    JSFunction* target = callLinkInfo.lastSeenCallee.get();
    if (!target)
        return CallLinkStatus();
    
    if (callLinkInfo.hasSeenClosure)
        return CallLinkStatus(target->executable(), target->structure());

    return CallLinkStatus(target);
}
Exemple #7
0
CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
    if (!profiledBlock->numberOfCallLinkInfos())
        return computeFromLLInt(profiledBlock, bytecodeIndex);
    
    if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
        return CallLinkStatus(0, true);
    
    CallLinkInfo& callLinkInfo = profiledBlock->getCallLinkInfo(bytecodeIndex);
    JSFunction* target = callLinkInfo.lastSeenCallee.get();
    if (!target)
        return computeFromLLInt(profiledBlock, bytecodeIndex);
    
    return CallLinkStatus(target, false, !!callLinkInfo.stub);
#else
    return CallLinkStatus(0, false, false);
#endif
}
Exemple #8
0
CallLinkStatus CallLinkStatus::computeFor(
    CodeBlock* profiledBlock, unsigned bytecodeIndex, const CallLinkInfoMap& map)
{
    ConcurrentJITLocker locker(profiledBlock->m_lock);
    
    UNUSED_PARAM(profiledBlock);
    UNUSED_PARAM(bytecodeIndex);
    UNUSED_PARAM(map);
#if ENABLE(DFG_JIT)
    ExitSiteData exitSiteData = computeExitSiteData(locker, profiledBlock, bytecodeIndex);
    if (exitSiteData.m_takesSlowPath)
        return takesSlowPath();
    
    CallLinkInfo* callLinkInfo = map.get(CodeOrigin(bytecodeIndex));
    if (!callLinkInfo)
        return computeFromLLInt(locker, profiledBlock, bytecodeIndex);
    
    return computeFor(locker, *callLinkInfo, exitSiteData);
#else
    return CallLinkStatus();
#endif
}