⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 242841 in webkit


Ignore:
Timestamp:
Mar 12, 2019, 7:34:28 PM (7 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] OSR entry should respect abstract values in addition to flush formats
https://bugs.webkit.org/show_bug.cgi?id=195653

Reviewed by Mark Lam.

JSTests:

  • stress/osr-entry-locals-none.js: Added.

Source/JavaScriptCore:

Let's consider the following graph.

Block #0

...
27:< 2:loc13> JSConstant(JS|UseAsOther, StringIdent, Strong:String (atomic) (identifier): , StructureID: 42679, bc#10, ExitValid)
...
28:< 2:loc13> ArithPow(DoubleRep:@437<Double>, Int32:@27, Double|UseAsOther, BytecodeDouble, Exits, bc#10, ExitValid)
29:<!0:-> MovHint(DoubleRep:@28<Double>, MustGen, loc7, W:SideState, ClobbersExit, bc#10, ExitValid)
30:< 1:-> SetLocal(DoubleRep:@28<Double>, loc7(M<Double>/FlushedDouble), machine:loc6, W:Stack(-8), bc#10, exit: bc#14, ExitValid) predicting BytecodeDouble
...
73:<!0:-> Jump(MustGen, T:#1, W:SideState, bc#71, ExitValid)

Block #1 (bc#71): (OSR target) pred, #0

...

102:<!2:loc15> GetLocal(Check:Untyped:@400, Double|MustGen|PureInt, BytecodeDouble, loc7(M<Double>/FlushedDouble), machine:loc6, R:Stack(-8), bc#120, ExitValid) predicting BytecodeDouble

...

CFA at @28 says it is invalid since there are type contradiction (Int32:@27 v.s. StringIdent). So, of course, we do not propagate #0's type information to #1 since we become invalid state.
However, #1 is still reachable since it is an OSR target. Since #0 was only the predecessor of #1, loc7's type information becomes None at the head of #1.
Since loc7's AbstractValue is None, @102 GetLocal emits breakpoint. It is OK as long as OSR entry fails because AbstractValue validation requires the given value is None type.

The issue here is that we skipped AbstractValue validation when we have FlushFormat information. Since loc7 has FlushedDouble format, DFG OSR entry code does not validate it against AbstractValue,
which is None. Then, we hit the breakpoint emitted by @102.

This patch performs AbstractValue validation against values even if we have FlushFormat. We should correctly configure AbstractValue for OSR entry's locals too to avoid unnecessary OSR entry
failures in the future but anyway validating locals with AbstractValue is correct behavior here since DFGSpeculativeJIT relies on that.

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r242838 r242841  
     12019-03-12  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] OSR entry should respect abstract values in addition to flush formats
     4        https://bugs.webkit.org/show_bug.cgi?id=195653
     5
     6        Reviewed by Mark Lam.
     7
     8        * stress/osr-entry-locals-none.js: Added.
     9
    1102019-03-12  Michael Saboff  <msaboff@apple.com>
    211
  • trunk/Source/JavaScriptCore/ChangeLog

    r242838 r242841  
     12019-03-12  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] OSR entry should respect abstract values in addition to flush formats
     4        https://bugs.webkit.org/show_bug.cgi?id=195653
     5
     6        Reviewed by Mark Lam.
     7
     8        Let's consider the following graph.
     9
     10        Block #0
     11            ...
     12            27:< 2:loc13> JSConstant(JS|UseAsOther, StringIdent, Strong:String (atomic) (identifier): , StructureID: 42679, bc#10, ExitValid)
     13            ...
     14            28:< 2:loc13> ArithPow(DoubleRep:@437<Double>, Int32:@27, Double|UseAsOther, BytecodeDouble, Exits, bc#10, ExitValid)
     15            29:<!0:->     MovHint(DoubleRep:@28<Double>, MustGen, loc7, W:SideState, ClobbersExit, bc#10, ExitValid)
     16            30:< 1:->     SetLocal(DoubleRep:@28<Double>, loc7(M<Double>/FlushedDouble), machine:loc6, W:Stack(-8), bc#10, exit: bc#14, ExitValid)  predicting BytecodeDouble
     17            ...
     18            73:<!0:->     Jump(MustGen, T:#1, W:SideState, bc#71, ExitValid)
     19
     20        Block #1 (bc#71): (OSR target) pred, #0
     21            ...
     22           102:<!2:loc15> GetLocal(Check:Untyped:@400, Double|MustGen|PureInt, BytecodeDouble, loc7(M<Double>/FlushedDouble), machine:loc6, R:Stack(-8), bc#120, ExitValid)  predicting BytecodeDouble
     23            ...
     24
     25        CFA at @28 says it is invalid since there are type contradiction (Int32:@27 v.s. StringIdent). So, of course, we do not propagate #0's type information to #1 since we become invalid state.
     26        However, #1 is still reachable since it is an OSR target. Since #0 was only the predecessor of #1, loc7's type information becomes None at the head of #1.
     27        Since loc7's AbstractValue is None, @102 GetLocal emits breakpoint. It is OK as long as OSR entry fails because AbstractValue validation requires the given value is None type.
     28
     29        The issue here is that we skipped AbstractValue validation when we have FlushFormat information. Since loc7 has FlushedDouble format, DFG OSR entry code does not validate it against AbstractValue,
     30        which is None. Then, we hit the breakpoint emitted by @102.
     31
     32        This patch performs AbstractValue validation against values even if we have FlushFormat. We should correctly configure AbstractValue for OSR entry's locals too to avoid unnecessary OSR entry
     33        failures in the future but anyway validating locals with AbstractValue is correct behavior here since DFGSpeculativeJIT relies on that.
     34
     35        * dfg/DFGOSREntry.cpp:
     36        (JSC::DFG::prepareOSREntry):
     37
    1382019-03-12  Michael Saboff  <msaboff@apple.com>
    239
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r241222 r242841  
    204204    for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
    205205        int localOffset = virtualRegisterForLocal(local).offset();
     206        JSValue value = exec->registers()[localOffset].asanUnsafeJSValue();
     207        if (!entry->m_expectedValues.local(local).validate(value)) {
     208            if (Options::verboseOSR()) {
     209                dataLog(
     210                    "    OSR failed because variable ", VirtualRegister(localOffset), " is ",
     211                    value, ", expected ",
     212                    entry->m_expectedValues.local(local), ".\n");
     213            }
     214            return 0;
     215        }
    206216        if (entry->m_localsForcedDouble.get(local)) {
    207             if (!exec->registers()[localOffset].asanUnsafeJSValue().isNumber()) {
     217            if (!value.isNumber()) {
    208218                if (Options::verboseOSR()) {
    209219                    dataLog(
    210220                        "    OSR failed because variable ", localOffset, " is ",
    211                         exec->registers()[localOffset].asanUnsafeJSValue(), ", expected number.\n");
     221                        value, ", expected number.\n");
    212222                }
    213223                return 0;
     
    216226        }
    217227        if (entry->m_localsForcedAnyInt.get(local)) {
    218             if (!exec->registers()[localOffset].asanUnsafeJSValue().isAnyInt()) {
     228            if (!value) {
    219229                if (Options::verboseOSR()) {
    220230                    dataLog(
    221231                        "    OSR failed because variable ", localOffset, " is ",
    222                         exec->registers()[localOffset].asanUnsafeJSValue(), ", expected ",
     232                        value, ", expected ",
    223233                        "machine int.\n");
    224234                }
     
    226236            }
    227237            continue;
    228         }
    229         if (!entry->m_expectedValues.local(local).validate(exec->registers()[localOffset].asanUnsafeJSValue())) {
    230             if (Options::verboseOSR()) {
    231                 dataLog(
    232                     "    OSR failed because variable ", VirtualRegister(localOffset), " is ",
    233                     exec->registers()[localOffset].asanUnsafeJSValue(), ", expected ",
    234                     entry->m_expectedValues.local(local), ".\n");
    235             }
    236             return 0;
    237238        }
    238239    }
Note: See TracChangeset for help on using the changeset viewer.