Changeset 192352 in webkit


Ignore:
Timestamp:
Nov 11, 2015 10:59:13 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

Crash in sorting-benchmark.js on ARM64 with full op_sub FTL coverage.
https://bugs.webkit.org/show_bug.cgi?id=150936

Reviewed by Michael Saboff.

The OSR entry thunk does not currently restore the callee saved registers that the baseline
JIT saves but the DFG does not. As a result, sorting-benchmark.js was crashing with the
following scenario:

  1. There exists 2 functions: benchmark() and bottom_up_merge_sort(). Let's call them A() and B() respectively for brevity.
  2. A() is FTL compiled.
  3. B() is FTL compiled.
  4. FTL A() calls FTL B(). FTL B() trashes register x26.
  5. FTL B() goes through an OSR exit, and deopts to baseline. The OSR exit off-ramp puts x26's original value in the baseline B()'s stash location for x26 in its stack frame. It expects baseline B() to restore x26 when it returns.
  6. Baseline B() gets DFG optimized, and we OSR enter into DFG B(). The OSR entry thunk does nothing to restore x26's original value. Hence, x26 contains whatever value FTL B() left in it.
  7. DFG B() returns to FTL A(). x26 is not one of the callee saved registers used by DFG B(). Hence, it does nothing to restore it.
  8. FTL A() tries to use x26 and crashes, because x26 contains FTL B()'s value for it, and not FTL A()'s.

This patch fixes this issue by having the OSR entry thunk restore all the callee saved
registers before running the DFG code.

No new test needed because this issue will be covered by sorting-benchmark.js as soon as
https://bugs.webkit.org/show_bug.cgi?id=150712 lands.

  • dfg/DFGThunks.cpp:

(JSC::DFG::osrEntryThunkGenerator):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r192348 r192352  
     12015-11-11  Mark Lam  <mark.lam@apple.com>
     2
     3        Crash in sorting-benchmark.js on ARM64 with full op_sub FTL coverage.
     4        https://bugs.webkit.org/show_bug.cgi?id=150936
     5
     6        Reviewed by Michael Saboff.
     7
     8        The OSR entry thunk does not currently restore the callee saved registers that the baseline
     9        JIT saves but the DFG does not.  As a result, sorting-benchmark.js was crashing with the
     10        following scenario:
     11
     12            1. There exists 2 functions: benchmark() and bottom_up_merge_sort().
     13               Let's call them A() and B() respectively for brevity.
     14            2. A() is FTL compiled.
     15            3. B() is FTL compiled.
     16            4. FTL A() calls FTL B().  FTL B() trashes register x26.
     17            5. FTL B() goes through an OSR exit, and deopts to baseline.  The OSR exit off-ramp
     18               puts x26's original value in the baseline B()'s stash location for x26 in its stack
     19               frame.  It expects baseline B() to restore x26 when it returns.
     20            6. Baseline B() gets DFG optimized, and we OSR enter into DFG B().
     21               The OSR entry thunk does nothing to restore x26's original value.  Hence, x26 contains
     22               whatever value FTL B() left in it.
     23            7. DFG B() returns to FTL A().
     24               x26 is not one of the callee saved registers used by DFG B().  Hence, it does nothing
     25               to restore it.
     26            8. FTL A() tries to use x26 and crashes, because x26 contains FTL B()'s value for it, and
     27               not FTL A()'s.
     28
     29        This patch fixes this issue by having the OSR entry thunk restore all the callee saved
     30        registers before running the DFG code.
     31
     32        No new test needed because this issue will be covered by sorting-benchmark.js as soon as
     33        https://bugs.webkit.org/show_bug.cgi?id=150712 lands.
     34
     35        * dfg/DFGThunks.cpp:
     36        (JSC::DFG::osrEntryThunkGenerator):
     37
    1382015-11-11  Benjamin Poulain  <bpoulain@apple.com>
    239
  • trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp

    r170876 r192352  
    9898MacroAssemblerCodeRef osrEntryThunkGenerator(VM* vm)
    9999{
    100     MacroAssembler jit;
    101    
     100    AssemblyHelpers jit(vm, nullptr);
     101
    102102    // We get passed the address of a scratch buffer. The first 8-byte slot of the buffer
    103103    // is the frame size. The second 8-byte slot is the pointer to where we are supposed to
     
    129129    MacroAssembler::Jump ok = jit.branchPtr(MacroAssembler::Above, GPRInfo::regT1, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000))));
    130130    jit.abortWithReason(DFGUnreasonableOSREntryJumpDestination);
     131
    131132    ok.link(&jit);
     133    RegisterSet usedRegisters(RegisterSet::stubUnavailableRegisters(), GPRInfo::regT1);
     134    jit.restoreCalleeSavesFromVMCalleeSavesBuffer(usedRegisters);
     135    jit.emitMaterializeTagCheckRegisters();
     136
    132137    jit.jump(GPRInfo::regT1);
    133138   
Note: See TracChangeset for help on using the changeset viewer.