Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 5009fc211624770cea06a9a0e592c10ba12e2597
      
https://github.com/WebKit/WebKit/commit/5009fc211624770cea06a9a0e592c10ba12e2597
  Author: Yusuke Suzuki <[email protected]>
  Date:   2026-10-13 (Tue, 13 Oct 2026)

  Changed paths:
    A JSTests/stress/instanceof-branch-fusion.js
    M Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

  Log Message:
  -----------
  [JSC] DFG should branch on op_instanceof result in each arm when jtrue / 
jfalse follows
https://bugs.webkit.org/show_bug.cgi?id=327327
rdar://189865582

Reviewed by Keith Miller and Tadeu Zagallo.

Currently, when we have a code like,

    function notInstance(term) {
        if (!(term instanceof Pair))
            return term;
        return term.car;
    }

`instanceof` creates a graph due to multiple complicated arms, and then
all of boolean results are combined into one phi, and then we jump based
on this phi result. However this form pessimizes the optimizations.

    #3  MatchStructure arm         D@74: MatchStructure(D@63, Object=>true)
                                   D@76: SetLocal(D@74, loc5)
                                   D@77: Jump(T:#7)
    #4  value-not-object arm       D@59: JSConstant(False)
                                   D@61: SetLocal(D@59, loc5)
                                   D@62: Jump(T:#7)
    #5  custom hasInstance arm     D@47: InstanceOfCustom(...)
                                   D@49: SetLocal(D@47, loc5)
                                   D@50: Jump(T:#7)

    #7 (bc#25)  preds: #5 #3 #4    D@78: GetLocal(loc5)
                                   D@79: Branch(D@78, T:#9, F:#8)
    #8 (bc#28)  return term
    #9 (bc#30)  CheckStructure(term, [Object]); GetByOffset(car); Return

In the above graph, due to unified blocks, D@74 MatchStructure's
filtering result is gone, and CheckStructure remains while we already
did Structure check via MatchStructure in one of the most common case.

So, we connect each jump directly when `instanceof` result is used with
`jtrue` / `jfalse`, like

    #3  MatchStructure arm         D@74: MatchStructure(D@63, Object=>true)
                                   D@76: SetLocal(D@74, loc5)
                                   D@77: Branch(D@74, T:#8, F:#7)
    #4  value-not-object arm       D@59: JSConstant(False)
                                   D@61: SetLocal(D@59, loc5)
                                   D@62: Branch(D@59, T:#8, F:#7)
    #5  custom hasInstance arm     D@47: InstanceOfCustom(...)
                                   D@49: SetLocal(D@47, loc5)
                                   D@50: Branch(D@47, T:#8, F:#7)

    #7 (bc#28)  preds: #5 #3 #4    return term
    #8 (bc#30)  preds: #5 #3 #4    CheckStructure(term, [Object]); 
GetByOffset(car); Return

                                   D@76: SetLocal(D@74, loc5)
                                   D@77: Jump(T:#7)
                                   D@61: SetLocal(D@59, loc5)
                                   D@62: Jump(T:#7)
                                   D@49: SetLocal(D@47, loc5)
                                   D@50: Jump(T:#7)

                                   D@79: Branch(D@78, T:#9, F:#8)

Then, eventually each MatchStructure, etc. are foled into constant, and
proper constant is propagated through the following blocks instead of
propagating the phi.

Test: JSTests/stress/instanceof-branch-fusion.js

* JSTests/stress/instanceof-branch-fusion.js: Added.
(shouldBe):
(Pair):
(Custom.Symbol.hasInstance):
(Custom):
(notInstance):
(isInstance):
(resultUsedAfterBranch):
(custom):
(loop):
(customJtrue):
(argumentDst):
(longBody):
(longBodyExpected):
(inlinedPredicate):
(inlinedCaller):
(catch):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):

Canonical link: https://commits.webkit.org/323664@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to