Changeset 200879 in webkit


Ignore:
Timestamp:
May 13, 2016, 1:16:29 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

We should have one calleeSaveRegistersBuffer per VMEntryFrame, not one per VM.
https://bugs.webkit.org/show_bug.cgi?id=157537
<rdar://problem/24794845>

Reviewed by Michael Saboff.

Source/JavaScriptCore:

The pre-existing code behaves this way:

  1. When JS code throws an exception, it saves callee save registers in the VM calleeSaveRegistersBuffer. These values are meant to be restored to the callee save registers later either at the catch handler or at the uncaught exception handler.
  1. If the Inspector is enable, the VM will invoke inspector C++ code to inspect the exception. That C++ code can change the values of the callee save registers.

The inspector code in turn re-enters the VM to execute JS inspector code.

The JS inspector code can run hot enough that we do an enterOptimizationCheck
on it. The enterOptimizationCheck first saves all callee save registers
into the VM calleeSaveRegistersBuffer.

This effectively overwrites the values in the VM calleeSaveRegistersBuffer
from (1).

  1. Eventually, execution returns to the catch handler or the uncaught exception handler which restores the overwritten values in the VM calleeSaveRegistersBuffer to the callee save registers.

When execution returns to the C++ code that entered the VM before (1), the
values in the callee registers are not what that code expects, and badness
and/or crashes ensues.

This patch applies the following fix:

  1. Allocate space in the VMEntryFrame for the calleeSaveRegistersBuffer. This ensures that each VM entry session has its own buffer to use, and will not corrupt the one from the previous VM entry session.

Delete the VM calleeSaveRegistersBuffer.

  1. Change all locations that uses the VM calleeSaveRegistersBuffer to use the calleeSaveRegistersBuffer in the current VMEntryFrame.
  1. Renamed all uses of the term "VMCalleeSavesBuffer" to "VMEntryFrameCalleeSavesBuffer".

This fix has been tested on the following configurations:

  1. JSC and layout tests on a debug ASan build for 64-bit x86_64.
  2. JSC tests on a release ASan build for 32-bit x86.
  3. JSC tests on a release normal (non-ASan) build for ARM64.
  4. JSC tests on a release normal (non-ASan) build for ARMv7 and ARMv7s.
  5. JSC tests on a release ASan CLOOP build for x86_64.

These test runs did not produce any new crashes. The ASan CLOOP has some
pre-existing crashes which are not due to this patch.

This bug can be tested by running the inspector/debugger/regress-133182.html test
on an ASan build.

  • bytecode/PolymorphicAccess.cpp:

(JSC::AccessGenerationState::emitExplicitExceptionHandler):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compileExceptionHandlers):

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGOSRExitCompiler32_64.cpp:

(JSC::DFG::OSRExitCompiler::compileExit):

  • dfg/DFGOSRExitCompiler64.cpp:

(JSC::DFG::OSRExitCompiler::compileExit):

  • dfg/DFGThunks.cpp:

(JSC::DFG::osrEntryThunkGenerator):

  • ftl/FTLCompile.cpp:

(JSC::FTL::compile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::lower):

  • ftl/FTLOSRExitCompiler.cpp:

(JSC::FTL::compileStub):

  • interpreter/Interpreter.cpp:

(JSC::UnwindFunctor::operator()):
(JSC::UnwindFunctor::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):
(JSC::UnwindFunctor::copyCalleeSavesToVMCalleeSavesBuffer): Deleted.

  • interpreter/Interpreter.h:

(JSC::NativeCallFrameTracer::NativeCallFrameTracer):

  • interpreter/VMEntryRecord.h:

(JSC::VMEntryRecord::calleeSaveRegistersBufferOffset):
(JSC::VMEntryRecord::prevTopCallFrame):
(JSC::VMEntryRecord::unsafePrevTopCallFrame):
(JSC::VMEntryFrame::vmEntryRecordOffset):
(JSC::VMEntryFrame::calleeSaveRegistersBufferOffset):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::emitRandomThunk):
(JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::restoreCalleeSavesFromVMCalleeSavesBuffer): Deleted.

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitRestoreSavedTagRegisters):
(JSC::AssemblyHelpers::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::copyCalleeSavesToVMCalleeSavesBuffer): Deleted.
(JSC::AssemblyHelpers::copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::emitEnterOptimizationCheck):
(JSC::JIT::privateCompileExceptionHandlers):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_throw):
(JSC::JIT::emit_op_catch):
(JSC::JIT::emitSlow_op_loop_hint):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_throw):
(JSC::JIT::emit_op_catch):

  • jit/ThunkGenerators.cpp:

(JSC::throwExceptionFromCallSlowPathGenerator):
(JSC::nativeForGenerator):

  • llint/LLIntThunks.cpp:

(JSC::vmEntryRecord):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/VM.h:

(JSC::VM::getCTIStub):
(JSC::VM::calleeSaveRegistersBufferOffset): Deleted.

  • wasm/WASMFunctionCompiler.h:

(JSC::WASMFunctionCompiler::endFunction):

LayoutTests:

  • inspector/debugger/regress-133182-expected.txt:
  • Rebased test results to update line numbers.
  • platform/mac/TestExpectations:
  • Unskip the test.
Location:
trunk
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r200876 r200879  
     12016-05-13  Mark Lam  <mark.lam@apple.com>
     2
     3        We should have one calleeSaveRegistersBuffer per VMEntryFrame, not one per VM.
     4        https://bugs.webkit.org/show_bug.cgi?id=157537
     5        <rdar://problem/24794845>
     6
     7        Reviewed by Michael Saboff.
     8
     9        * inspector/debugger/regress-133182-expected.txt:
     10        - Rebased test results to update line numbers.
     11        * platform/mac/TestExpectations:
     12        - Unskip the test.
     13
    1142016-05-13  Doug Russell  <d_russell@apple.com>
    215
  • trunk/LayoutTests/inspector/debugger/regress-133182-expected.txt

    r188142 r200879  
    1 CONSOLE MESSAGE: line 47: [1] Testing statement '({}).a.b.c.d;'
    2 CONSOLE MESSAGE: line 48: [1] Paused and about to step
    3 CONSOLE MESSAGE: line 60: [1] Resumed
    4 CONSOLE MESSAGE: line 52: [1] Paused after stepping
    5 CONSOLE MESSAGE: line 60: [1] Resumed
     1CONSOLE MESSAGE: line 56: [1] Testing statement '({}).a.b.c.d;'
     2CONSOLE MESSAGE: line 57: [1] Paused and about to step
     3CONSOLE MESSAGE: line 69: [1] Resumed
     4CONSOLE MESSAGE: line 61: [1] Paused after stepping
     5CONSOLE MESSAGE: line 69: [1] Resumed
    66CONSOLE MESSAGE: line 1: TypeError: undefined is not an object (evaluating '({}).a.b')
    7 CONSOLE MESSAGE: line 47: [2] Testing statement 'exceptionBasic();'
    8 CONSOLE MESSAGE: line 48: [2] Paused and about to step
    9 CONSOLE MESSAGE: line 60: [2] Resumed
    10 CONSOLE MESSAGE: line 52: [2] Paused after stepping
    11 CONSOLE MESSAGE: line 60: [2] Resumed
     7CONSOLE MESSAGE: line 56: [2] Testing statement 'exceptionBasic();'
     8CONSOLE MESSAGE: line 57: [2] Paused and about to step
     9CONSOLE MESSAGE: line 69: [2] Resumed
     10CONSOLE MESSAGE: line 61: [2] Paused after stepping
     11CONSOLE MESSAGE: line 69: [2] Resumed
    1212CONSOLE MESSAGE: line 3: TypeError: undefined is not an object (evaluating '({}).a.b')
    13 CONSOLE MESSAGE: line 47: [3] Testing statement 'exceptionDOM();'
    14 CONSOLE MESSAGE: line 48: [3] Paused and about to step
    15 CONSOLE MESSAGE: line 60: [3] Resumed
    16 CONSOLE MESSAGE: line 52: [3] Paused after stepping
    17 CONSOLE MESSAGE: line 60: [3] Resumed
     13CONSOLE MESSAGE: line 56: [3] Testing statement 'exceptionDOM();'
     14CONSOLE MESSAGE: line 57: [3] Paused and about to step
     15CONSOLE MESSAGE: line 69: [3] Resumed
     16CONSOLE MESSAGE: line 61: [3] Paused after stepping
     17CONSOLE MESSAGE: line 69: [3] Resumed
    1818CONSOLE MESSAGE: line 8: NotFoundError: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.
    19 CONSOLE MESSAGE: line 47: [4] Testing statement 'exceptionInHostFunction();'
    20 CONSOLE MESSAGE: line 48: [4] Paused and about to step
    21 CONSOLE MESSAGE: line 60: [4] Resumed
    22 CONSOLE MESSAGE: line 52: [4] Paused after stepping
    23 CONSOLE MESSAGE: line 60: [4] Resumed
     19CONSOLE MESSAGE: line 56: [4] Testing statement 'exceptionInHostFunction();'
     20CONSOLE MESSAGE: line 57: [4] Paused and about to step
     21CONSOLE MESSAGE: line 69: [4] Resumed
     22CONSOLE MESSAGE: line 61: [4] Paused after stepping
     23CONSOLE MESSAGE: line 69: [4] Resumed
    2424CONSOLE MESSAGE: line 24: exception in host function
    25 CONSOLE MESSAGE: line 47: [5] Testing statement 'throwString();'
    26 CONSOLE MESSAGE: line 48: [5] Paused and about to step
    27 CONSOLE MESSAGE: line 60: [5] Resumed
    28 CONSOLE MESSAGE: line 52: [5] Paused after stepping
    29 CONSOLE MESSAGE: line 60: [5] Resumed
     25CONSOLE MESSAGE: line 56: [5] Testing statement 'throwString();'
     26CONSOLE MESSAGE: line 57: [5] Paused and about to step
     27CONSOLE MESSAGE: line 69: [5] Resumed
     28CONSOLE MESSAGE: line 61: [5] Paused after stepping
     29CONSOLE MESSAGE: line 69: [5] Resumed
    3030CONSOLE MESSAGE: line 13: exception string
    31 CONSOLE MESSAGE: line 47: [6] Testing statement 'throwParam({x:1});'
    32 CONSOLE MESSAGE: line 48: [6] Paused and about to step
    33 CONSOLE MESSAGE: line 60: [6] Resumed
    34 CONSOLE MESSAGE: line 52: [6] Paused after stepping
    35 CONSOLE MESSAGE: line 60: [6] Resumed
     31CONSOLE MESSAGE: line 56: [6] Testing statement 'throwParam({x:1});'
     32CONSOLE MESSAGE: line 57: [6] Paused and about to step
     33CONSOLE MESSAGE: line 69: [6] Resumed
     34CONSOLE MESSAGE: line 61: [6] Paused after stepping
     35CONSOLE MESSAGE: line 69: [6] Resumed
    3636CONSOLE MESSAGE: line 18: [object Object]
    37 CONSOLE MESSAGE: line 47: [7] Testing statement 'throwParam(new Error('error message'));'
    38 CONSOLE MESSAGE: line 48: [7] Paused and about to step
    39 CONSOLE MESSAGE: line 60: [7] Resumed
    40 CONSOLE MESSAGE: line 52: [7] Paused after stepping
    41 CONSOLE MESSAGE: line 60: [7] Resumed
     37CONSOLE MESSAGE: line 56: [7] Testing statement 'throwParam(new Error('error message'));'
     38CONSOLE MESSAGE: line 57: [7] Paused and about to step
     39CONSOLE MESSAGE: line 69: [7] Resumed
     40CONSOLE MESSAGE: line 61: [7] Paused after stepping
     41CONSOLE MESSAGE: line 69: [7] Resumed
    4242CONSOLE MESSAGE: line 18: Error: error message
    4343Regression test for https://bugs.webkit.org/show_bug.cgi?id=133182
  • trunk/LayoutTests/platform/mac/TestExpectations

    r200804 r200879  
    732732inspector/debugger/nested-inspectors.html
    733733inspector/debugger/pause-reason.html
    734 inspector/debugger/regress-133182.html
    735734
    736735webkit.org/b/124311 compositing/regions/transform-transparent-positioned-video-inside-region.html [ ImageOnlyFailure ]
  • trunk/Source/JavaScriptCore/ChangeLog

    r200866 r200879  
     12016-05-13  Mark Lam  <mark.lam@apple.com>
     2
     3        We should have one calleeSaveRegistersBuffer per VMEntryFrame, not one per VM.
     4        https://bugs.webkit.org/show_bug.cgi?id=157537
     5        <rdar://problem/24794845>
     6
     7        Reviewed by Michael Saboff.
     8
     9        The pre-existing code behaves this way:
     10
     11        1. When JS code throws an exception, it saves callee save registers in
     12           the VM calleeSaveRegistersBuffer.  These values are meant to be restored
     13           to the callee save registers later either at the catch handler or at the
     14           uncaught exception handler.
     15
     16        2. If the Inspector is enable, the VM will invoke inspector C++ code to inspect
     17           the exception.  That C++ code can change the values of the callee save
     18           registers.
     19
     20           The inspector code in turn re-enters the VM to execute JS inspector code.
     21
     22           The JS inspector code can run hot enough that we do an enterOptimizationCheck
     23           on it.  The enterOptimizationCheck first saves all callee save registers
     24           into the VM calleeSaveRegistersBuffer.
     25
     26           This effectively overwrites the values in the VM calleeSaveRegistersBuffer
     27           from (1).
     28
     29        3. Eventually, execution returns to the catch handler or the uncaught exception
     30           handler which restores the overwritten values in the VM
     31           calleeSaveRegistersBuffer to the callee save registers.
     32
     33           When execution returns to the C++ code that entered the VM before (1), the
     34           values in the callee registers are not what that code expects, and badness
     35           and/or crashes ensues.
     36
     37        This patch applies the following fix:
     38       
     39        1. Allocate space in the VMEntryFrame for the calleeSaveRegistersBuffer.
     40           This ensures that each VM entry session has its own buffer to use, and will
     41           not corrupt the one from the previous VM entry session.
     42
     43           Delete the VM calleeSaveRegistersBuffer.
     44
     45        2. Change all locations that uses the VM calleeSaveRegistersBuffer to use the
     46           calleeSaveRegistersBuffer in the current VMEntryFrame.
     47
     48        3. Renamed all uses of the term "VMCalleeSavesBuffer" to
     49           "VMEntryFrameCalleeSavesBuffer".
     50
     51        This fix has been tested on the following configurations:
     52        1. JSC and layout tests on a debug ASan build for 64-bit x86_64.
     53        2. JSC tests on a release ASan build for 32-bit x86.
     54        3. JSC tests on a release normal (non-ASan) build for ARM64.
     55        4. JSC tests on a release normal (non-ASan) build for ARMv7 and ARMv7s.
     56        5. JSC tests on a release ASan CLOOP build for x86_64.
     57
     58        These test runs did not produce any new crashes.  The ASan CLOOP has some
     59        pre-existing crashes which are not due to this patch.
     60
     61        This bug can be tested by running the inspector/debugger/regress-133182.html test
     62        on an ASan build.
     63
     64        * bytecode/PolymorphicAccess.cpp:
     65        (JSC::AccessGenerationState::emitExplicitExceptionHandler):
     66        * dfg/DFGJITCompiler.cpp:
     67        (JSC::DFG::JITCompiler::compileExceptionHandlers):
     68        * dfg/DFGOSREntry.cpp:
     69        (JSC::DFG::prepareOSREntry):
     70        * dfg/DFGOSRExitCompiler.cpp:
     71        * dfg/DFGOSRExitCompiler32_64.cpp:
     72        (JSC::DFG::OSRExitCompiler::compileExit):
     73        * dfg/DFGOSRExitCompiler64.cpp:
     74        (JSC::DFG::OSRExitCompiler::compileExit):
     75        * dfg/DFGThunks.cpp:
     76        (JSC::DFG::osrEntryThunkGenerator):
     77        * ftl/FTLCompile.cpp:
     78        (JSC::FTL::compile):
     79        * ftl/FTLLowerDFGToB3.cpp:
     80        (JSC::FTL::DFG::LowerDFGToB3::lower):
     81        * ftl/FTLOSRExitCompiler.cpp:
     82        (JSC::FTL::compileStub):
     83        * interpreter/Interpreter.cpp:
     84        (JSC::UnwindFunctor::operator()):
     85        (JSC::UnwindFunctor::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):
     86        (JSC::UnwindFunctor::copyCalleeSavesToVMCalleeSavesBuffer): Deleted.
     87        * interpreter/Interpreter.h:
     88        (JSC::NativeCallFrameTracer::NativeCallFrameTracer):
     89        * interpreter/VMEntryRecord.h:
     90        (JSC::VMEntryRecord::calleeSaveRegistersBufferOffset):
     91        (JSC::VMEntryRecord::prevTopCallFrame):
     92        (JSC::VMEntryRecord::unsafePrevTopCallFrame):
     93        (JSC::VMEntryFrame::vmEntryRecordOffset):
     94        (JSC::VMEntryFrame::calleeSaveRegistersBufferOffset):
     95        * jit/AssemblyHelpers.cpp:
     96        (JSC::AssemblyHelpers::emitRandomThunk):
     97        (JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer):
     98        (JSC::AssemblyHelpers::restoreCalleeSavesFromVMCalleeSavesBuffer): Deleted.
     99        * jit/AssemblyHelpers.h:
     100        (JSC::AssemblyHelpers::emitRestoreSavedTagRegisters):
     101        (JSC::AssemblyHelpers::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):
     102        (JSC::AssemblyHelpers::copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer):
     103        (JSC::AssemblyHelpers::copyCalleeSavesToVMCalleeSavesBuffer): Deleted.
     104        (JSC::AssemblyHelpers::copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer): Deleted.
     105        * jit/JIT.cpp:
     106        (JSC::JIT::emitEnterOptimizationCheck):
     107        (JSC::JIT::privateCompileExceptionHandlers):
     108        * jit/JITOpcodes.cpp:
     109        (JSC::JIT::emit_op_throw):
     110        (JSC::JIT::emit_op_catch):
     111        (JSC::JIT::emitSlow_op_loop_hint):
     112        * jit/JITOpcodes32_64.cpp:
     113        (JSC::JIT::emit_op_throw):
     114        (JSC::JIT::emit_op_catch):
     115        * jit/ThunkGenerators.cpp:
     116        (JSC::throwExceptionFromCallSlowPathGenerator):
     117        (JSC::nativeForGenerator):
     118        * llint/LLIntThunks.cpp:
     119        (JSC::vmEntryRecord):
     120        * llint/LowLevelInterpreter.asm:
     121        * llint/LowLevelInterpreter32_64.asm:
     122        * llint/LowLevelInterpreter64.asm:
     123        * runtime/VM.h:
     124        (JSC::VM::getCTIStub):
     125        (JSC::VM::calleeSaveRegistersBufferOffset): Deleted.
     126        * wasm/WASMFunctionCompiler.h:
     127        (JSC::WASMFunctionCompiler::endFunction):
     128
    11292016-05-13  Beth Dakin  <bdakin@apple.com>
    2130
  • trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp

    r200606 r200879  
    173173{
    174174    restoreScratch();
    175     jit->copyCalleeSavesToVMCalleeSavesBuffer();
     175    jit->copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    176176    if (needsToRestoreRegistersIfException()) {
    177177        // To the JIT that produces the original exception handling
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r200034 r200879  
    140140        m_exceptionChecksWithCallFrameRollback.link(this);
    141141
    142         copyCalleeSavesToVMCalleeSavesBuffer();
     142        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    143143
    144144        // lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*).
     
    160160        m_exceptionChecks.link(this);
    161161
    162         copyCalleeSavesToVMCalleeSavesBuffer();
     162        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    163163
    164164        // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r200034 r200879  
    11/*
    2  * Copyright (C) 2011, 2013, 2014, 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    317317
    318318    unsigned registerCount = registerSaveLocations->size();
     319    VMEntryRecord* record = vmEntryRecord(vm->topVMEntryFrame);
    319320    for (unsigned i = 0; i < registerCount; i++) {
    320321        RegisterAtOffset currentEntry = registerSaveLocations->at(i);
    321322        if (dontSaveRegisters.get(currentEntry.reg()))
    322323            continue;
    323         RegisterAtOffset* vmCalleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
    324        
    325         *(bitwise_cast<intptr_t*>(pivot - 1) - currentEntry.offsetAsIndex()) = vm->calleeSaveRegistersBuffer[vmCalleeSavesEntry->offsetAsIndex()];
     324        RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
     325       
     326        *(bitwise_cast<intptr_t*>(pivot - 1) - currentEntry.offsetAsIndex()) = record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()];
    326327    }
    327328#endif
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp

    r198364 r200879  
    152152            // We are acting as a defacto op_catch because we arrive here from genericUnwind().
    153153            // So, we must restore our call frame and stack pointer.
    154             jit.restoreCalleeSavesFromVMCalleeSavesBuffer();
     154            jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
    155155            jit.loadPtr(vm->addressOfCallFrameForCatch(), GPRInfo::callFrameRegister);
    156156            jit.addPtr(CCallHelpers::TrustedImm32(codeBlock->stackPointerOffset() * sizeof(Register)),
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp

    r200606 r200879  
    256256
    257257    if (exit.isExceptionHandler())
    258         m_jit.copyCalleeSavesToVMCalleeSavesBuffer();
     258        m_jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    259259
    260260    // Do all data format conversions and store the results into the stack.
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp

    r200606 r200879  
    266266
    267267    if (exit.isExceptionHandler())
    268         m_jit.copyCalleeSavesToVMCalleeSavesBuffer();
     268        m_jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    269269
    270270    // Do all data format conversions and store the results into the stack.
  • trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp

    r194772 r200879  
    136136
    137137    ok.link(&jit);
    138     jit.restoreCalleeSavesFromVMCalleeSavesBuffer();
     138    jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
    139139    jit.emitMaterializeTagCheckRegisters();
    140140
  • trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp

    r198600 r200879  
    122122    // Emit the exception handler.
    123123    *state.exceptionHandler = jit.label();
    124     jit.copyCalleeSavesToVMCalleeSavesBuffer();
     124    jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    125125    jit.move(MacroAssembler::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0);
    126126    jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r200701 r200879  
    207207                AllowMacroScratchRegisterUsage allowScratch(jit);
    208208               
    209                 jit.copyCalleeSavesToVMCalleeSavesBuffer();
     209                jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    210210                jit.move(CCallHelpers::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0);
    211211                jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
  • trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp

    r200606 r200879  
    187187    if (exit.isGenericUnwindHandler()) {
    188188        RELEASE_ASSERT(vm->callFrameForCatch); // The first time we hit this exit, like at all other times, this field should be non-null.
    189         jit.restoreCalleeSavesFromVMCalleeSavesBuffer();
     189        jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
    190190        jit.loadPtr(vm->addressOfCallFrameForCatch(), MacroAssembler::framePointerRegister);
    191191        jit.addPtr(CCallHelpers::TrustedImm32(codeBlock->stackPointerOffset() * sizeof(Register)),
     
    442442    RegisterAtOffsetList* vmCalleeSaves = vm->getAllCalleeSaveRegisterOffsets();
    443443    RegisterSet vmCalleeSavesToSkip = RegisterSet::stackRegisters();
    444     if (exit.isExceptionHandler())
    445         jit.move(CCallHelpers::TrustedImmPtr(vm->calleeSaveRegistersBuffer), GPRInfo::regT1);
     444    if (exit.isExceptionHandler()) {
     445        jit.loadPtr(&vm->topVMEntryFrame, GPRInfo::regT1);
     446        jit.addPtr(CCallHelpers::TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), GPRInfo::regT1);
     447    }
    446448
    447449    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r200856 r200879  
    696696                profiler->exceptionUnwind(m_callFrame);
    697697
    698             copyCalleeSavesToVMCalleeSavesBuffer(visitor);
     698            copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
    699699
    700700            return StackVisitor::Done;
    701701        }
    702702
    703         copyCalleeSavesToVMCalleeSavesBuffer(visitor);
     703        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
    704704
    705705        return StackVisitor::Continue;
     
    707707
    708708private:
    709     void copyCalleeSavesToVMCalleeSavesBuffer(StackVisitor& visitor) const
     709    void copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
    710710    {
    711711#if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     
    729729
    730730        unsigned registerCount = currentCalleeSaves->size();
     731        VMEntryRecord* record = vmEntryRecord(vm.topVMEntryFrame);
    731732        for (unsigned i = 0; i < registerCount; i++) {
    732733            RegisterAtOffset currentEntry = currentCalleeSaves->at(i);
    733734            if (dontCopyRegisters.get(currentEntry.reg()))
    734735                continue;
    735             RegisterAtOffset* vmCalleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
     736            RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
    736737           
    737             vm.calleeSaveRegistersBuffer[vmCalleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex());
     738            record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex());
    738739        }
    739740#else
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r199852 r200879  
    146146            ASSERT(vm);
    147147            ASSERT(callFrame);
    148             ASSERT(callFrame < vm->topVMEntryFrame);
     148            ASSERT(reinterpret_cast<void*>(callFrame) < reinterpret_cast<void*>(vm->topVMEntryFrame));
    149149            vm->topCallFrame = callFrame;
    150150        }
  • trunk/Source/JavaScriptCore/interpreter/VMEntryRecord.h

    r196658 r200879  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#define VMEntryRecord_h
    2828
     29#include "GPRInfo.h"
     30
    2931namespace JSC {
    3032
    31 typedef void VMEntryFrame;
    32 
     33struct VMEntryFrame;
    3334class ExecState;
    3435class VM;
     
    4344    VMEntryFrame* m_prevTopVMEntryFrame;
    4445
     46#if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     47    intptr_t calleeSaveRegistersBuffer[NUMBER_OF_CALLEE_SAVES_REGISTERS];
     48#endif
     49
    4550    ExecState* prevTopCallFrame() { return m_prevTopCallFrame; }
    4651    SUPPRESS_ASAN ExecState* unsafePrevTopCallFrame() { return m_prevTopCallFrame; }
     
    5257extern "C" VMEntryRecord* vmEntryRecord(VMEntryFrame*);
    5358
     59struct VMEntryFrame {
     60#if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     61    static ptrdiff_t vmEntryRecordOffset()
     62    {
     63        VMEntryFrame* fakeVMEntryFrame = reinterpret_cast<VMEntryFrame*>(0x1000);
     64        VMEntryRecord* record = vmEntryRecord(fakeVMEntryFrame);
     65        return static_cast<ptrdiff_t>(
     66            reinterpret_cast<char*>(record) - reinterpret_cast<char*>(fakeVMEntryFrame));
     67    }
     68
     69    static ptrdiff_t calleeSaveRegistersBufferOffset()
     70    {
     71        return vmEntryRecordOffset() + OBJECT_OFFSETOF(VMEntryRecord, calleeSaveRegistersBuffer);
     72    }
     73#endif
     74};
     75
    5476} // namespace JSC
    5577
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r199166 r200879  
    567567#endif
    568568
    569 void AssemblyHelpers::restoreCalleeSavesFromVMCalleeSavesBuffer()
     569void AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer()
    570570{
    571571#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    572     char* sourceBuffer = bitwise_cast<char*>(m_vm->calleeSaveRegistersBuffer);
    573 
    574572    RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets();
    575573    RegisterSet dontRestoreRegisters = RegisterSet::stackRegisters();
    576574    unsigned registerCount = allCalleeSaves->size();
    577    
     575
     576    GPRReg scratch = InvalidGPRReg;
     577    unsigned scratchGPREntryIndex = 0;
     578
     579    // Use the first GPR entry's register as our scratch.
    578580    for (unsigned i = 0; i < registerCount; i++) {
    579581        RegisterAtOffset entry = allCalleeSaves->at(i);
    580582        if (dontRestoreRegisters.get(entry.reg()))
    581583            continue;
    582         if (entry.reg().isGPR())
    583             loadPtr(static_cast<void*>(sourceBuffer + entry.offset()), entry.reg().gpr());
    584         else
    585             loadDouble(TrustedImmPtr(sourceBuffer + entry.offset()), entry.reg().fpr());
    586     }
     584        if (entry.reg().isGPR()) {
     585            scratchGPREntryIndex = i;
     586            scratch = entry.reg().gpr();
     587            break;
     588        }
     589    }
     590    ASSERT(scratch != InvalidGPRReg);
     591
     592    loadPtr(&m_vm->topVMEntryFrame, scratch);
     593    addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), scratch);
     594
     595    // Restore all callee saves except for the scratch.
     596    for (unsigned i = 0; i < registerCount; i++) {
     597        RegisterAtOffset entry = allCalleeSaves->at(i);
     598        if (dontRestoreRegisters.get(entry.reg()))
     599            continue;
     600        if (entry.reg().isGPR()) {
     601            if (i != scratchGPREntryIndex)
     602                loadPtr(Address(scratch, entry.offset()), entry.reg().gpr());
     603        } else
     604            loadDouble(Address(scratch, entry.offset()), entry.reg().fpr());
     605    }
     606
     607    // Restore the callee save value of the scratch.
     608    RegisterAtOffset entry = allCalleeSaves->at(scratchGPREntryIndex);
     609    ASSERT(!dontRestoreRegisters.get(entry.reg()));
     610    ASSERT(entry.reg().isGPR());
     611    ASSERT(scratch == entry.reg().gpr());
     612    loadPtr(Address(scratch, entry.offset()), scratch);
    587613#endif
    588614}
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r200606 r200879  
    314314    }
    315315
    316     void copyCalleeSavesToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
     316    void copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
    317317    {
    318318#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    319319        GPRReg temp1 = usedRegisters.getFreeGPR(0);
    320320
    321         move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
     321        loadPtr(&m_vm->topVMEntryFrame, temp1);
     322        addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), temp1);
    322323
    323324        RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets();
     
    339340    }
    340341
    341     void restoreCalleeSavesFromVMCalleeSavesBuffer();
    342 
    343     void copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
     342    void restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
     343
     344    void copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
    344345    {
    345346#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     
    352353
    353354        // Copy saved calleeSaves on stack or unsaved calleeSaves in register to vm calleeSave buffer
    354         move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
     355        loadPtr(&m_vm->topVMEntryFrame, temp1);
     356        addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), temp1);
    355357
    356358        RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets();
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r200658 r200879  
    9797    ASSERT(!m_bytecodeOffset);
    9898
    99     copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer();
     99    copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer();
    100100
    101101    callOperation(operationOptimize, m_bytecodeOffset);
     
    786786        m_exceptionChecksWithCallFrameRollback.link(this);
    787787
    788         copyCalleeSavesToVMCalleeSavesBuffer();
     788        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    789789
    790790        // lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*).
     
    805805        m_exceptionChecks.link(this);
    806806
    807         copyCalleeSavesToVMCalleeSavesBuffer();
     807        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    808808
    809809        // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r200102 r200879  
    443443{
    444444    ASSERT(regT0 == returnValueGPR);
    445     copyCalleeSavesToVMCalleeSavesBuffer();
     445    copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    446446    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
    447447    callOperationNoExceptionCheck(operationThrow, regT0);
     
    519519void JIT::emit_op_catch(Instruction* currentInstruction)
    520520{
    521     restoreCalleeSavesFromVMCalleeSavesBuffer();
     521    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
    522522
    523523    move(TrustedImmPtr(m_vm), regT3);
     
    936936        linkSlowCase(iter);
    937937
    938         copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer();
     938        copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer();
    939939
    940940        callOperation(operationOptimize, m_bytecodeOffset);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r200102 r200879  
    788788{
    789789    ASSERT(regT0 == returnValueGPR);
    790     copyCalleeSavesToVMCalleeSavesBuffer();
     790    copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    791791    emitLoad(currentInstruction[1].u.operand, regT1, regT0);
    792792    callOperationNoExceptionCheck(operationThrow, regT1, regT0);
     
    848848void JIT::emit_op_catch(Instruction* currentInstruction)
    849849{
    850     restoreCalleeSavesFromVMCalleeSavesBuffer();
     850    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
    851851
    852852    move(TrustedImmPtr(m_vm), regT3);
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r200422 r200879  
    6767    jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
    6868
    69     jit.copyCalleeSavesToVMCalleeSavesBuffer();
     69    jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    7070
    7171    jit.setupArguments(CCallHelpers::TrustedImmPtr(vm), GPRInfo::callFrameRegister);
     
    356356    exceptionHandler.link(&jit);
    357357
    358     jit.copyCalleeSavesToVMCalleeSavesBuffer();
     358    jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    359359    jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
    360360
  • trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp

    r189201 r200879  
    117117    intptr_t stackAlignment = stackAlignmentBytes();
    118118    intptr_t VMEntryTotalFrameSize = (sizeof(VMEntryRecord) + (stackAlignment - 1)) & ~(stackAlignment - 1);
    119     return reinterpret_cast<VMEntryRecord*>(static_cast<char*>(entryFrame) - VMEntryTotalFrameSize);
     119    return reinterpret_cast<VMEntryRecord*>(reinterpret_cast<char*>(entryFrame) - VMEntryTotalFrameSize);
    120120}
    121121
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r200586 r200879  
    569569end
    570570
    571 macro copyCalleeSavesToVMCalleeSavesBuffer(vm, temp)
     571macro copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(vm, temp)
    572572    if ARM64 or X86_64 or X86_64_WIN
    573         leap VM::calleeSaveRegistersBuffer[vm], temp
     573        loadp VM::topVMEntryFrame[vm], temp
     574        vmEntryRecord(temp, temp)
     575        leap VMEntryRecord::calleeSaveRegistersBuffer[temp], temp
    574576        if ARM64
    575577            storep csr0, [temp]
     
    609611end
    610612
    611 macro restoreCalleeSavesFromVMCalleeSavesBuffer(vm, temp)
     613macro restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(vm, temp)
    612614    if ARM64 or X86_64 or X86_64_WIN
    613         leap VM::calleeSaveRegistersBuffer[vm], temp
     615        loadp VM::topVMEntryFrame[vm], temp
     616        vmEntryRecord(temp, temp)
     617        leap VMEntryRecord::calleeSaveRegistersBuffer[temp], temp
    614618        if ARM64
    615619            loadp [temp], csr0
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r200102 r200879  
    303303    andp MarkedBlockMask, t3
    304304    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    305     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
     305    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
    306306    loadp VM::callFrameForCatch[t3], cfr
    307307    storep 0, VM::callFrameForCatch[t3]
     
    19161916    andp MarkedBlockMask, t3
    19171917    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    1918     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
     1918    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
    19191919    loadp VM::callFrameForCatch[t3], cfr
    19201920    storep 0, VM::callFrameForCatch[t3]
     
    19661966    andp MarkedBlockMask, t1
    19671967    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
    1968     copyCalleeSavesToVMCalleeSavesBuffer(t1, t2)
     1968    copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(t1, t2)
    19691969    jmp VM::targetMachinePCForThrow[t1]
    19701970
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r200102 r200879  
    275275    andp MarkedBlockMask, t3
    276276    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    277     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
     277    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
    278278    loadp VM::callFrameForCatch[t3], cfr
    279279    storep 0, VM::callFrameForCatch[t3]
     
    17951795    andp MarkedBlockMask, t3
    17961796    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    1797     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
     1797    restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
    17981798    loadp VM::callFrameForCatch[t3], cfr
    17991799    storep 0, VM::callFrameForCatch[t3]
     
    18411841    andp MarkedBlockMask, t1
    18421842    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
    1843     copyCalleeSavesToVMCalleeSavesBuffer(t1, t2)
     1843    copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(t1, t2)
    18441844
    18451845    callSlowPath(_llint_slow_path_handle_exception)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r200658 r200879  
    3535#include "ExecutableAllocator.h"
    3636#include "FunctionHasExecutedCache.h"
    37 #if ENABLE(JIT)
    38 #include "GPRInfo.h"
    39 #endif
    4037#include "Heap.h"
    4138#include "Intrinsic.h"
     
    385382    Interpreter* interpreter;
    386383#if ENABLE(JIT)
    387 #if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    388     intptr_t calleeSaveRegistersBuffer[NUMBER_OF_CALLEE_SAVES_REGISTERS];
    389 
    390     static ptrdiff_t calleeSaveRegistersBufferOffset()
    391     {
    392         return OBJECT_OFFSETOF(VM, calleeSaveRegistersBuffer);
    393     }
    394 #endif // NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    395 
    396384    std::unique_ptr<JITThunks> jitStubs;
    397385    MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator)
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h

    r200399 r200879  
    238238            m_exceptionChecks.link(this);
    239239
    240             copyCalleeSavesToVMCalleeSavesBuffer();
     240            copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
    241241
    242242            // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
Note: See TracChangeset for help on using the changeset viewer.