Ignore:
Timestamp:
Sep 14, 2013, 5:57:42 PM (12 years ago)
Author:
[email protected]
Message:

It should be easy to add new nodes that do OSR forward rewiring in both DFG and FTL
https://bugs.webkit.org/show_bug.cgi?id=121371

Reviewed by Sam Weinig.

Forward rewiring is a tricky part of OSR that handles the following:

a: Something(...)

SetLocal(@a, locX)

b: Int32ToDouble(@a)
c: SomethingThatExits(@b)

<no further uses of @a or @b>

Note that at @c, OSR will think that locX->@a, but @a will be dead. So it must be
smart enough to find @b, which contains an equivalent value. It must do this for
any identity functions we support. Currently we support four such functions.

Currently the code for doing this is basically duplicated between the DFG and the
FTL. Also both versions of the code have some really weirdly written logic for
picking the "best" identity function to use.

We should fix this by simply having a way to ask "is this node an identity
function, and if so, then how good is it?" Then both the DFG and FTL could use
this and have no hard-wired knowledge of those identity functions.

While we're at it, this also changes some terminology because I found the use of
the word "needs" confusing. Note that this retains the somewhat confusing behavior
that we don't search all possible forward/backward uses. We only search one step
in each direction. This is because we only need to handle cases that FixupPhase
and the parser insert. All other code that tries to insert intermediate conversion
nodes should ensure to Phantom the original node. For example, the following
transformation is illegal:

Before:

x: SomethingThatExits(@a)


After:

w: Conversion(@a)
x: SomethingThatExits(@w)


The correct form of that transformation is one of these:

Correct #1:

v: DoAllChecks(@a) exit here
w: Conversion(@a)
x: Something(@w)
no exit


Correct #2:

w: Conversion(@a)
x: SomethingThatExits(@w)
y: Phantom(@a)


Correct #3:

w: Conversion(@a)
x: SomethingThatExits(@w, @a)


Note that we use #3 for some heap accesses, but of course it requires that the
node you're using has an extra slot for a "dummy" use child.

Broadly speaking though, such transformations should be relegated to something
below DFG IR, like LLVM IR.

  • dfg/DFGNodeType.h:

(JSC::DFG::forwardRewiringSelectionScore):
(JSC::DFG::needsOSRForwardRewiring):

  • dfg/DFGVariableEventStream.cpp:

(JSC::DFG::VariableEventStream::reconstruct):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r155735 r155793  
    30883088            bool found = false;
    30893089           
    3090             if (needsOSRBackwardRewiring(node->op())) {
     3090            if (permitsOSRBackwardRewiring(node->op())) {
    30913091                node = node->child1().node();
    30923092                if (tryToSetConstantExitArgument(exit, index, node))
     
    30973097           
    30983098            if (!found) {
    3099                 Node* int32ToDouble = 0;
    3100                 Node* valueToInt32 = 0;
    3101                 Node* uint32ToNumber = 0;
    3102                 Node* doubleAsInt32 = 0;
     3099                Node* bestNode = 0;
     3100                unsigned bestScore = 0;
    31033101               
    31043102                HashSet<Node*>::iterator iter = m_live.begin();
     
    31123110                    if (candidate->child1() != node)
    31133111                        continue;
    3114                     switch (candidate->op()) {
    3115                     case Int32ToDouble:
    3116                         int32ToDouble = candidate;
    3117                         break;
    3118                     case ValueToInt32:
    3119                         valueToInt32 = candidate;
    3120                         break;
    3121                     case UInt32ToNumber:
    3122                         uint32ToNumber = candidate;
    3123                         break;
    3124                     case DoubleAsInt32:
    3125                         uint32ToNumber = candidate;
    3126                         break;
    3127                     default:
    3128                         ASSERT(!needsOSRForwardRewiring(candidate->op()));
    3129                         break;
    3130                     }
     3112                    unsigned myScore = forwardRewiringSelectionScore(candidate->op());
     3113                    if (myScore <= bestScore)
     3114                        continue;
     3115                    bestNode = candidate;
     3116                    bestScore = myScore;
    31313117                }
    31323118               
    3133                 if (doubleAsInt32)
    3134                     node = doubleAsInt32;
    3135                 else if (int32ToDouble)
    3136                     node = int32ToDouble;
    3137                 else if (valueToInt32)
    3138                     node = valueToInt32;
    3139                 else if (uint32ToNumber)
    3140                     node = uint32ToNumber;
    3141                
    3142                 if (isLive(node))
     3119                if (bestNode) {
     3120                    ASSERT(isLive(bestNode));
     3121                    node = bestNode;
    31433122                    found = true;
     3123                }
    31443124            }
    31453125           
Note: See TracChangeset for help on using the changeset viewer.