- Source/JavaScriptCore/ChangeLog +31 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2014-01-15  Filip Pizlo  <fpizlo@apple.com>
2
3
        reentrant-caching sometimes fails with LLInt disabled
4
        https://bugs.webkit.org/show_bug.cgi?id=126781
5
6
        Reviewed by NOBODY (OOPS!).
7
        
8
        The lookupExceptionHandler->genericUnwind->handleUncaughtException paths need to
9
        be resilient against the frame from which we claim to be throwing the exception
10
        being the sentinel frame.
11
12
        * dfg/DFGJITCompiler.cpp:
13
        (JSC::DFG::JITCompiler::compileExceptionHandlers):
14
        * ftl/FTLCompile.cpp:
15
        (JSC::FTL::fixFunctionBasedOnStackMaps):
16
        * interpreter/Interpreter.cpp:
17
        (JSC::Interpreter::unwind):
18
        * interpreter/Interpreter.h:
19
        (JSC::NativeCallFrameTracer::NativeCallFrameTracer):
20
        * jit/CCallHelpers.h:
21
        (JSC::CCallHelpers::setupArguments):
22
        * jit/JIT.cpp:
23
        (JSC::JIT::privateCompileExceptionHandlers):
24
        * jit/JITOperations.cpp:
25
        * jit/JITOperations.h:
26
        * jit/Repatch.cpp:
27
        (JSC::tryBuildGetByIDList):
28
        * jit/ThunkGenerators.cpp:
29
        (JSC::throwExceptionFromCallSlowPathGenerator):
30
        * llint/LowLevelInterpreter64.asm:
31
1
2014-01-14  Filip Pizlo  <fpizlo@apple.com>
32
2014-01-14  Filip Pizlo  <fpizlo@apple.com>
2
33
3
        FTL slow path calls in inline caches should be down with exceptions
34
        FTL slow path calls in inline caches should be down with exceptions
- Source/JavaScriptCore/dfg/DFGJITCompiler.cpp -3 / +6 lines
Lines 121-142 void JITCompiler::compileExceptionHandle Source/JavaScriptCore/dfg/DFGJITCompiler.cpp_sec1
121
121
122
    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
122
    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
123
        m_exceptionChecksWithCallFrameRollback.link(this);
123
        m_exceptionChecksWithCallFrameRollback.link(this);
124
        emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR0);
124
        emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR1);
125
        doLookup = jump();
125
        doLookup = jump();
126
    }
126
    }
127
127
128
    if (!m_exceptionChecks.empty())
128
    if (!m_exceptionChecks.empty())
129
        m_exceptionChecks.link(this);
129
        m_exceptionChecks.link(this);
130
130
131
    // lookupExceptionHandler is passed one argument, the exec (the CallFrame*).
131
    // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
132
    move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
132
    move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
133
133
134
    if (doLookup.isSet())
134
    if (doLookup.isSet())
135
        doLookup.link(this);
135
        doLookup.link(this);
136
136
137
    move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
138
137
#if CPU(X86)
139
#if CPU(X86)
138
    // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
140
    // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
139
    poke(GPRInfo::argumentGPR0);
141
    poke(GPRInfo::argumentGPR0);
142
    poke(GPRInfo::argumentGPR1, 1);
140
#endif
143
#endif
141
    m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
144
    m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
142
    jumpToExceptionHandler();
145
    jumpToExceptionHandler();
- Source/JavaScriptCore/ftl/FTLCompile.cpp -1 / +2 lines
Lines 179-185 static void fixFunctionBasedOnStackMaps( Source/JavaScriptCore/ftl/FTLCompile.cpp_sec1
179
        checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
179
        checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
180
        checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
180
        checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
181
        
181
        
182
        checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
182
        checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
183
        checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
183
        MacroAssembler::Call call = checkJIT.call();
184
        MacroAssembler::Call call = checkJIT.call();
184
        checkJIT.jumpToExceptionHandler();
185
        checkJIT.jumpToExceptionHandler();
185
        
186
        
- Source/JavaScriptCore/interpreter/Interpreter.cpp +9 lines
Lines 649-654 private: Source/JavaScriptCore/interpreter/Interpreter.cpp_sec1
649
649
650
NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
650
NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
651
{
651
{
652
    if (callFrame->isVMEntrySentinel()) {
653
        // This happens when we throw stack overflow in a function that is called
654
        // directly from callToJavaScript.  Stack overflow throws the exception in the
655
        // context of the caller.  In that case the caller is the sentinel frame.  The
656
        // right thing to do is to pretend that the exception is uncaught so that we
657
        // go to the uncaught exception handler, which returns through callToJavaScript.
658
        return 0;
659
    }
660
    
652
    CodeBlock* codeBlock = callFrame->codeBlock();
661
    CodeBlock* codeBlock = callFrame->codeBlock();
653
    bool isTermination = false;
662
    bool isTermination = false;
654
663
- Source/JavaScriptCore/interpreter/Interpreter.h +9 lines
Lines 180-185 namespace JSC { Source/JavaScriptCore/interpreter/Interpreter.h_sec1
180
            ASSERT(!callFrame->isVMEntrySentinel());
180
            ASSERT(!callFrame->isVMEntrySentinel());
181
            vm->topCallFrame = callFrame;
181
            vm->topCallFrame = callFrame;
182
        }
182
        }
183
        
184
        enum VMEntrySentinelOKTag { VMEntrySentinelOK };
185
        ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame, VMEntrySentinelOKTag)
186
        {
187
            ASSERT(vm);
188
            ASSERT(callFrame);
189
            if (!callFrame->isVMEntrySentinel())
190
                vm->topCallFrame = callFrame;
191
        }
183
    };
192
    };
184
193
185
    class Interpreter {
194
    class Interpreter {
- Source/JavaScriptCore/jit/CCallHelpers.h +13 lines
Lines 95-100 public: Source/JavaScriptCore/jit/CCallHelpers.h_sec1
95
        addCallArgument(arg2);
95
        addCallArgument(arg2);
96
    }
96
    }
97
    
97
    
98
    ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1, GPRReg arg2)
99
    {
100
        resetCallArguments();
101
        addCallArgument(arg1);
102
        addCallArgument(arg2);
103
    }
104
    
98
    ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
105
    ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
99
    {
106
    {
100
        resetCallArguments();
107
        resetCallArguments();
Lines 939-944 public: Source/JavaScriptCore/jit/CCallHelpers.h_sec2
939
        move(arg1, GPRInfo::argumentGPR0);
946
        move(arg1, GPRInfo::argumentGPR0);
940
    }
947
    }
941
948
949
    ALWAYS_INLINE void setupArguments(TrustedImmPtr arg1, GPRReg arg2)
950
    {
951
        move(arg2, GPRInfo::argumentGPR1);
952
        move(arg1, GPRInfo::argumentGPR0);
953
    }
954
    
942
    ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
955
    ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
943
    {
956
    {
944
        setupTwoStubArgsGPR<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
957
        setupTwoStubArgsGPR<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
- Source/JavaScriptCore/jit/JIT.cpp -2 / +5 lines
Lines 702-708 void JIT::privateCompileExceptionHandler Source/JavaScriptCore/jit/JIT.cpp_sec1
702
702
703
    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
703
    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
704
        m_exceptionChecksWithCallFrameRollback.link(this);
704
        m_exceptionChecksWithCallFrameRollback.link(this);
705
        emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR0);
705
        emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR1);
706
        doLookup = jump();
706
        doLookup = jump();
707
    }
707
    }
708
708
Lines 710-723 void JIT::privateCompileExceptionHandler Source/JavaScriptCore/jit/JIT.cpp_sec2
710
        m_exceptionChecks.link(this);
710
        m_exceptionChecks.link(this);
711
    
711
    
712
    // lookupExceptionHandler is passed one argument, the exec (the CallFrame*).
712
    // lookupExceptionHandler is passed one argument, the exec (the CallFrame*).
713
    move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
713
    move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
714
714
715
    if (doLookup.isSet())
715
    if (doLookup.isSet())
716
        doLookup.link(this);
716
        doLookup.link(this);
717
717
718
    move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
719
718
#if CPU(X86)
720
#if CPU(X86)
719
    // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
721
    // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
720
    poke(GPRInfo::argumentGPR0);
722
    poke(GPRInfo::argumentGPR0);
723
    poke(GPRInfo::argumentGPR1, 1);
721
#endif
724
#endif
722
    m_calls.append(CallRecord(call(), (unsigned)-1, FunctionPtr(lookupExceptionHandler).value()));
725
    m_calls.append(CallRecord(call(), (unsigned)-1, FunctionPtr(lookupExceptionHandler).value()));
723
    jumpToExceptionHandler();
726
    jumpToExceptionHandler();
- Source/JavaScriptCore/jit/JITOperations.cpp -4 / +3 lines
Lines 1731-1742 void JIT_OPERATION operationThrow(ExecSt Source/JavaScriptCore/jit/JITOperations.cpp_sec1
1731
    genericUnwind(vm, exec, exceptionValue);
1731
    genericUnwind(vm, exec, exceptionValue);
1732
}
1732
}
1733
1733
1734
void JIT_OPERATION lookupExceptionHandler(ExecState* exec)
1734
void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
1735
{
1735
{
1736
    VM* vm = &exec->vm();
1736
    NativeCallFrameTracer tracer(vm, exec, NativeCallFrameTracer::VMEntrySentinelOK);
1737
    NativeCallFrameTracer tracer(vm, exec);
1738
1737
1739
    JSValue exceptionValue = exec->exception();
1738
    JSValue exceptionValue = vm->exception();
1740
    ASSERT(exceptionValue);
1739
    ASSERT(exceptionValue);
1741
    
1740
    
1742
    genericUnwind(vm, exec, exceptionValue);
1741
    genericUnwind(vm, exec, exceptionValue);
- Source/JavaScriptCore/jit/JITOperations.h -2 / +2 lines
Lines 183-190 typedef JSString* JIT_OPERATION (*Jss_JI Source/JavaScriptCore/jit/JITOperations.h_sec1
183
183
184
// This method is used to lookup an exception hander, keyed by faultLocation, which is
184
// This method is used to lookup an exception hander, keyed by faultLocation, which is
185
// the return location from one of the calls out to one of the helper operations above.
185
// the return location from one of the calls out to one of the helper operations above.
186
    
186
187
void JIT_OPERATION lookupExceptionHandler(ExecState*) WTF_INTERNAL;
187
void JIT_OPERATION lookupExceptionHandler(VM*, ExecState*) WTF_INTERNAL;
188
void JIT_OPERATION operationVMHandleException(ExecState*) WTF_INTERNAL;
188
void JIT_OPERATION operationVMHandleException(ExecState*) WTF_INTERNAL;
189
189
190
void JIT_OPERATION operationThrowStackOverflowError(ExecState*, CodeBlock*) WTF_INTERNAL;
190
void JIT_OPERATION operationThrowStackOverflowError(ExecState*, CodeBlock*) WTF_INTERNAL;
- Source/JavaScriptCore/jit/Repatch.cpp -1 / +1 lines
Lines 559-565 static bool tryBuildGetByIDList(ExecStat Source/JavaScriptCore/jit/Repatch.cpp_sec1
559
#endif
559
#endif
560
            success = stubJit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
560
            success = stubJit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
561
            
561
            
562
            stubJit.setupArgumentsExecState();
562
            stubJit.setupArguments(CCallHelpers::TrustedImmPtr(vm), GPRInfo::callFrameRegister);
563
            handlerCall = stubJit.call();
563
            handlerCall = stubJit.call();
564
            stubJit.jumpToExceptionHandler();
564
            stubJit.jumpToExceptionHandler();
565
        } else {
565
        } else {
- Source/JavaScriptCore/jit/ThunkGenerators.cpp -1 / +1 lines
Lines 66-72 MacroAssemblerCodeRef throwExceptionFrom Source/JavaScriptCore/jit/ThunkGenerators.cpp_sec1
66
    // even though we won't use it.
66
    // even though we won't use it.
67
    jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
67
    jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
68
68
69
    jit.setupArgumentsExecState();
69
    jit.setupArguments(CCallHelpers::TrustedImmPtr(vm), GPRInfo::callFrameRegister);
70
    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(lookupExceptionHandler)), GPRInfo::nonArgGPR0);
70
    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(lookupExceptionHandler)), GPRInfo::nonArgGPR0);
71
    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
71
    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
72
    jit.call(GPRInfo::nonArgGPR0);
72
    jit.call(GPRInfo::nonArgGPR0);
- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm -2 / +5 lines
Lines 267-276 _handleUncaughtException: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec1
267
    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
267
    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
268
    loadp VM::callFrameForThrow[t3], cfr
268
    loadp VM::callFrameForThrow[t3], cfr
269
269
270
    # So far, we've unwound the stack to the frame just below the sentinel frame.
270
    # So far, we've unwound the stack to the frame just below the sentinel frame, except
271
    # We need to pop to the sentinel frame and do the necessary clean up for
271
    # in the case of stack overflow in the first function called from callToJavaScript.
272
    # Check if we need to pop to the sentinel frame and do the necessary clean up for
272
    # returning to the caller C frame.
273
    # returning to the caller C frame.
274
    bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
273
    loadp CallerFrame[cfr], cfr
275
    loadp CallerFrame[cfr], cfr
276
.handleUncaughtExceptionAlreadyIsSentinel:
274
277
275
    loadp Callee[cfr], t3 # VM
278
    loadp Callee[cfr], t3 # VM
276
    loadp ScopeChain[cfr], t5 # previous topCallFrame
279
    loadp ScopeChain[cfr], t5 # previous topCallFrame

Return to Bug 126781