Ignore:
Timestamp:
Aug 26, 2014, 9:46:10 AM (11 years ago)
Author:
[email protected]
Message:

Unreviewed, rolling out r172940.
https://bugs.webkit.org/show_bug.cgi?id=136256

Caused assertions on fast/storage/serialized-script-
value.html, and possibly flakiness on more tests (Requested by
ap on #webkit).

Reverted changeset:

"FTL should be able to do polymorphic call inlining"
https://bugs.webkit.org/show_bug.cgi?id=135145
http://trac.webkit.org/changeset/172940

Location:
trunk/Source/JavaScriptCore/bytecode
Files:
7 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp

    r172940 r172961  
    8484    if (!!lastSeenCallee && !Heap::isMarked(lastSeenCallee.get()))
    8585        lastSeenCallee.clear();
    86    
    87     if (callEdgeProfile) {
    88         WTF::loadLoadFence();
    89         callEdgeProfile->visitWeak();
    90     }
    9186}
    9287
  • trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h

    r172940 r172961  
    2727#define CallLinkInfo_h
    2828
    29 #include "CallEdgeProfile.h"
    3029#include "ClosureCallStubRoutine.h"
    3130#include "CodeLocation.h"
     
    3534#include "Opcode.h"
    3635#include "WriteBarrier.h"
    37 #include <wtf/OwnPtr.h>
    3836#include <wtf/SentinelLinkedList.h>
    3937
     
    9189    unsigned slowPathCount;
    9290    CodeOrigin codeOrigin;
    93     OwnPtr<CallEdgeProfile> callEdgeProfile;
    9491
    9592    bool isLinked() { return stub || callee; }
  • trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp

    r172940 r172961  
    3333#include "JSCInlines.h"
    3434#include <wtf/CommaPrinter.h>
    35 #include <wtf/ListDump.h>
    3635
    3736namespace JSC {
     
    4039
    4140CallLinkStatus::CallLinkStatus(JSValue value)
    42     : m_couldTakeSlowPath(false)
     41    : m_callTarget(value)
     42    , m_executable(0)
     43    , m_couldTakeSlowPath(false)
    4344    , m_isProved(false)
    4445{
    45     if (!value || !value.isCell()) {
    46         m_couldTakeSlowPath = true;
     46    if (!value || !value.isCell())
    4747        return;
    48     }
    49    
    50     m_edges.append(CallEdge(CallVariant(value.asCell()), 1));
     48   
     49    if (!value.asCell()->inherits(JSFunction::info()))
     50        return;
     51   
     52    m_executable = jsCast<JSFunction*>(value.asCell())->executable();
     53}
     54
     55JSFunction* CallLinkStatus::function() const
     56{
     57    if (!m_callTarget || !m_callTarget.isCell())
     58        return 0;
     59   
     60    if (!m_callTarget.asCell()->inherits(JSFunction::info()))
     61        return 0;
     62   
     63    return jsCast<JSFunction*>(m_callTarget.asCell());
     64}
     65
     66InternalFunction* CallLinkStatus::internalFunction() const
     67{
     68    if (!m_callTarget || !m_callTarget.isCell())
     69        return 0;
     70   
     71    if (!m_callTarget.asCell()->inherits(InternalFunction::info()))
     72        return 0;
     73   
     74    return jsCast<InternalFunction*>(m_callTarget.asCell());
     75}
     76
     77Intrinsic CallLinkStatus::intrinsicFor(CodeSpecializationKind kind) const
     78{
     79    if (!m_executable)
     80        return NoIntrinsic;
     81   
     82    return m_executable->intrinsicFor(kind);
    5183}
    5284
     
    5688    UNUSED_PARAM(bytecodeIndex);
    5789#if ENABLE(DFG_JIT)
    58     if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell))) {
     90    if (profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction))) {
    5991        // We could force this to be a closure call, but instead we'll just assume that it
    6092        // takes slow path.
     
    94126        return computeFromLLInt(locker, profiledBlock, bytecodeIndex);
    95127   
    96     return computeFor(locker, profiledBlock, *callLinkInfo, exitSiteData);
     128    return computeFor(locker, *callLinkInfo, exitSiteData);
    97129#else
    98130    return CallLinkStatus();
     
    108140#if ENABLE(DFG_JIT)
    109141    exitSiteData.m_takesSlowPath =
    110         profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadType, exitingJITType))
     142        profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache, exitingJITType))
    111143        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable, exitingJITType));
    112144    exitSiteData.m_badFunction =
    113         profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell, exitingJITType));
     145        profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction, exitingJITType));
    114146#else
    115147    UNUSED_PARAM(locker);
     
    123155
    124156#if ENABLE(JIT)
    125 CallLinkStatus CallLinkStatus::computeFor(
    126     const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, CallLinkInfo& callLinkInfo)
    127 {
    128     // We don't really need this, but anytime we have to debug this code, it becomes indispensable.
    129     UNUSED_PARAM(profiledBlock);
    130    
    131     if (Options::callStatusShouldUseCallEdgeProfile()) {
    132         // Always trust the call edge profile over anything else since this has precise counts.
    133         // It can make the best possible decision because it never "forgets" what happened for any
    134         // call, with the exception of fading out the counts of old calls (for example if the
    135         // counter type is 16-bit then calls that happened more than 2^16 calls ago are given half
    136         // weight, and this compounds for every 2^15 [sic] calls after that). The combination of
    137         // high fidelity for recent calls and fading for older calls makes this the most useful
    138         // mechamism of choosing how to optimize future calls.
    139         CallEdgeProfile* edgeProfile = callLinkInfo.callEdgeProfile.get();
    140         WTF::loadLoadFence();
    141         if (edgeProfile) {
    142             CallLinkStatus result = computeFromCallEdgeProfile(edgeProfile);
    143             if (!!result)
    144                 return result;
    145         }
    146     }
    147    
    148     return computeFromCallLinkInfo(locker, callLinkInfo);
    149 }
    150 
    151 CallLinkStatus CallLinkStatus::computeFromCallLinkInfo(
    152     const ConcurrentJITLocker&, CallLinkInfo& callLinkInfo)
     157CallLinkStatus CallLinkStatus::computeFor(const ConcurrentJITLocker&, CallLinkInfo& callLinkInfo)
    153158{
    154159    // Note that despite requiring that the locker is held, this code is racy with respect
     
    173178    JSFunction* target = callLinkInfo.lastSeenCallee.get();
    174179    if (!target)
    175         return takesSlowPath();
     180        return CallLinkStatus();
    176181   
    177182    if (callLinkInfo.hasSeenClosure)
     
    181186}
    182187
    183 CallLinkStatus CallLinkStatus::computeFromCallEdgeProfile(CallEdgeProfile* edgeProfile)
    184 {
    185     // In cases where the call edge profile saw nothing, use the CallLinkInfo instead.
    186     if (!edgeProfile->totalCalls())
    187         return CallLinkStatus();
    188    
    189     // To do anything meaningful, we require that the majority of calls are to something we
    190     // know how to handle.
    191     unsigned numCallsToKnown = edgeProfile->numCallsToKnownCells();
    192     unsigned numCallsToUnknown = edgeProfile->numCallsToNotCell() + edgeProfile->numCallsToUnknownCell();
    193    
    194     // We require that the majority of calls were to something that we could possibly inline.
    195     if (numCallsToKnown <= numCallsToUnknown)
    196         return takesSlowPath();
    197    
    198     // We require that the number of such calls is greater than some minimal threshold, so that we
    199     // avoid inlining completely cold calls.
    200     if (numCallsToKnown < Options::frequentCallThreshold())
    201         return takesSlowPath();
    202    
    203     CallLinkStatus result;
    204     result.m_edges = edgeProfile->callEdges();
    205     result.m_couldTakeSlowPath = !!numCallsToUnknown;
    206     result.m_canTrustCounts = true;
    207    
    208     return result;
    209 }
    210 
    211188CallLinkStatus CallLinkStatus::computeFor(
    212     const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, CallLinkInfo& callLinkInfo,
    213     ExitSiteData exitSiteData)
    214 {
    215     CallLinkStatus result = computeFor(locker, profiledBlock, callLinkInfo);
     189    const ConcurrentJITLocker& locker, CallLinkInfo& callLinkInfo, ExitSiteData exitSiteData)
     190{
     191    if (exitSiteData.m_takesSlowPath)
     192        return takesSlowPath();
     193   
     194    CallLinkStatus result = computeFor(locker, callLinkInfo);
    216195    if (exitSiteData.m_badFunction)
    217196        result.makeClosureCall();
    218     if (exitSiteData.m_takesSlowPath)
    219         result.m_couldTakeSlowPath = true;
    220197   
    221198    return result;
     
    251228        {
    252229            ConcurrentJITLocker locker(dfgCodeBlock->m_lock);
    253             map.add(info.codeOrigin, computeFor(locker, dfgCodeBlock, info, exitSiteData));
     230            map.add(info.codeOrigin, computeFor(locker, info, exitSiteData));
    254231        }
    255232    }
     
    280257}
    281258
    282 bool CallLinkStatus::isClosureCall() const
    283 {
    284     for (unsigned i = m_edges.size(); i--;) {
    285         if (m_edges[i].callee().isClosureCall())
    286             return true;
    287     }
    288     return false;
    289 }
    290 
    291 void CallLinkStatus::makeClosureCall()
    292 {
    293     ASSERT(!m_isProved);
    294     for (unsigned i = m_edges.size(); i--;)
    295         m_edges[i] = m_edges[i].despecifiedClosure();
    296    
    297     if (!ASSERT_DISABLED) {
    298         // Doing this should not have created duplicates, because the CallEdgeProfile
    299         // should despecify closures if doing so would reduce the number of known callees.
    300         for (unsigned i = 0; i < m_edges.size(); ++i) {
    301             for (unsigned j = i + 1; j < m_edges.size(); ++j)
    302                 ASSERT(m_edges[i].callee() != m_edges[j].callee());
    303         }
    304     }
    305 }
    306 
    307259void CallLinkStatus::dump(PrintStream& out) const
    308260{
     
    320272        out.print(comma, "Could Take Slow Path");
    321273   
    322     out.print(listDump(m_edges));
     274    if (m_callTarget)
     275        out.print(comma, "Known target: ", m_callTarget);
     276   
     277    if (m_executable) {
     278        out.print(comma, "Executable/CallHash: ", RawPointer(m_executable));
     279        if (!isCompilationThread())
     280            out.print("/", m_executable->hashFor(CodeForCall));
     281    }
    323282}
    324283
  • trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h

    r172940 r172961  
    4747public:
    4848    CallLinkStatus()
    49         : m_couldTakeSlowPath(false)
     49        : m_executable(0)
     50        , m_couldTakeSlowPath(false)
    5051        , m_isProved(false)
    51         , m_canTrustCounts(false)
    5252    {
    5353    }
     
    6262    explicit CallLinkStatus(JSValue);
    6363   
    64     CallLinkStatus(CallVariant variant)
    65         : m_edges(1, CallEdge(variant, 1))
     64    CallLinkStatus(ExecutableBase* executable)
     65        : m_executable(executable)
    6666        , m_couldTakeSlowPath(false)
    6767        , m_isProved(false)
    68         , m_canTrustCounts(false)
    6968    {
    7069    }
     
    9493    // Computes the status assuming that we never took slow path and never previously
    9594    // exited.
    96     static CallLinkStatus computeFor(const ConcurrentJITLocker&, CodeBlock*, CallLinkInfo&);
    97     static CallLinkStatus computeFor(
    98         const ConcurrentJITLocker&, CodeBlock*, CallLinkInfo&, ExitSiteData);
     95    static CallLinkStatus computeFor(const ConcurrentJITLocker&, CallLinkInfo&);
     96    static CallLinkStatus computeFor(const ConcurrentJITLocker&, CallLinkInfo&, ExitSiteData);
    9997#endif
    10098   
     
    110108        CodeBlock*, CodeOrigin, const CallLinkInfoMap&, const ContextMap&);
    111109   
    112     bool isSet() const { return !m_edges.isEmpty() || m_couldTakeSlowPath; }
     110    bool isSet() const { return m_callTarget || m_executable || m_couldTakeSlowPath; }
    113111   
    114112    bool operator!() const { return !isSet(); }
    115113   
    116114    bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
     115    bool isClosureCall() const { return m_executable && !m_callTarget; }
    117116   
    118     CallEdgeList edges() const { return m_edges; }
    119     unsigned size() const { return m_edges.size(); }
    120     CallEdge at(unsigned i) const { return m_edges[i]; }
    121     CallEdge operator[](unsigned i) const { return at(i); }
     117    JSValue callTarget() const { return m_callTarget; }
     118    JSFunction* function() const;
     119    InternalFunction* internalFunction() const;
     120    Intrinsic intrinsicFor(CodeSpecializationKind) const;
     121    ExecutableBase* executable() const { return m_executable; }
    122122    bool isProved() const { return m_isProved; }
    123     bool canOptimize() const { return !m_edges.isEmpty(); }
    124     bool canTrustCounts() const { return m_canTrustCounts; }
    125    
    126     bool isClosureCall() const; // Returns true if any callee is a closure call.
     123    bool canOptimize() const { return (m_callTarget || m_executable) && !m_couldTakeSlowPath; }
    127124   
    128125    void dump(PrintStream&) const;
    129126   
    130127private:
    131     void makeClosureCall();
     128    void makeClosureCall()
     129    {
     130        ASSERT(!m_isProved);
     131        // Turn this into a closure call.
     132        m_callTarget = JSValue();
     133    }
    132134   
    133135    static CallLinkStatus computeFromLLInt(const ConcurrentJITLocker&, CodeBlock*, unsigned bytecodeIndex);
    134 #if ENABLE(JIT)
    135     static CallLinkStatus computeFromCallEdgeProfile(CallEdgeProfile*);
    136     static CallLinkStatus computeFromCallLinkInfo(
    137         const ConcurrentJITLocker&, CallLinkInfo&);
    138 #endif
    139136   
    140     CallEdgeList m_edges;
     137    JSValue m_callTarget;
     138    ExecutableBase* m_executable;
    141139    bool m_couldTakeSlowPath;
    142140    bool m_isProved;
    143     bool m_canTrustCounts;
    144141};
    145142
  • trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h

    r172940 r172961  
    155155    }
    156156   
    157     static bool isNormalCall(Kind kind)
    158     {
    159         switch (kind) {
    160         case Call:
    161         case Construct:
    162             return true;
    163         default:
    164             return false;
    165         }
    166     }
    167    
    168157    Vector<ValueRecovery> arguments; // Includes 'this'.
    169158    WriteBarrier<ScriptExecutable> executable;
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp

    r172940 r172961  
    3939    case BadType:
    4040        return "BadType";
    41     case BadCell:
    42         return "BadCell";
     41    case BadFunction:
     42        return "BadFunction";
    4343    case BadExecutable:
    4444        return "BadExecutable";
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.h

    r172940 r172961  
    3232    ExitKindUnset,
    3333    BadType, // We exited because a type prediction was wrong.
    34     BadCell, // We exited because we made an incorrect assumption about what cell we would see. Usually used for function checks.
     34    BadFunction, // We exited because we made an incorrect assumption about what function we would see.
    3535    BadExecutable, // We exited because we made an incorrect assumption about what executable we would see.
    3636    BadCache, // We exited because an inline cache was wrong.
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp

    r172940 r172961  
    188188                        list->at(listIndex).stubRoutine());
    189189                    callLinkStatus = std::make_unique<CallLinkStatus>(
    190                         CallLinkStatus::computeFor(
    191                             locker, profiledBlock, *stub->m_callLinkInfo, callExitSiteData));
     190                        CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData));
    192191                    break;
    193192                }
  • trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp

    r172940 r172961  
    248248                        std::make_unique<CallLinkStatus>(
    249249                            CallLinkStatus::computeFor(
    250                                 locker, profiledBlock, *stub->m_callLinkInfo, callExitSiteData));
     250                                locker, *stub->m_callLinkInfo, callExitSiteData));
    251251                   
    252252                    variant = PutByIdVariant::setter(
Note: See TracChangeset for help on using the changeset viewer.