Ignore:
Timestamp:
Aug 26, 2012, 5:49:25 PM (13 years ago)
Author:
[email protected]
Message:

Finally inlining should correctly track the catch context
https://bugs.webkit.org/show_bug.cgi?id=94986
<rdar://problem/11753784>

Reviewed by Sam Weinig.

Source/JavaScriptCore:

This fixes two behaviors:

1) Throwing from a finally block. Previously, we would seem to reenter the finally

block - though only once.


2) Executing a finally block from some nested context, for example due to a

'continue', 'break', or 'return' in the try. This would execute the finally
block in the context of of the try block, which could lead to either scope depth
mismatches or reexecutions of the finally block on throw, similarly to (1) but
for different reasons.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC):
(JSC::BytecodeGenerator::pushFinallyContext):
(JSC::BytecodeGenerator::emitComplexJumpScopes):
(JSC::BytecodeGenerator::pushTry):
(JSC::BytecodeGenerator::popTryAndEmitCatch):

  • bytecompiler/BytecodeGenerator.h:

(FinallyContext):
(TryData):
(JSC):
(TryContext):
(TryRange):
(BytecodeGenerator):

  • bytecompiler/NodesCodegen.cpp:

(JSC::TryNode::emitBytecode):

LayoutTests:

  • fast/js/jsc-test-list:
  • fast/js/script-tests/throw-from-finally.js: Added.
  • fast/js/throw-from-finally.html: Added.
  • fast/js/throw-from-finally-expected.txt: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r124729 r126718  
    19711971    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column());
    19721972
     1973    ASSERT(m_catchBlock || m_finallyBlock);
     1974
    19731975    RefPtr<Label> tryStartLabel = generator.newLabel();
     1976    generator.emitLabel(tryStartLabel.get());
     1977   
    19741978    if (m_finallyBlock)
    19751979        generator.pushFinallyContext(m_finallyBlock);
    1976 
    1977     generator.emitLabel(tryStartLabel.get());
     1980    TryData* tryData = generator.pushTry(tryStartLabel.get());
     1981
    19781982    generator.emitNode(dst, m_tryBlock);
    19791983
     
    19861990        // Uncaught exception path: the catch block.
    19871991        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
    1988         RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
     1992        RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
     1993       
     1994        if (m_finallyBlock) {
     1995            // If the catch block throws an exception and we have a finally block, then the finally
     1996            // block should "catch" that exception.
     1997            tryData = generator.pushTry(here.get());
     1998        }
     1999       
    19892000        generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
    19902001        generator.emitNode(dst, m_catchBlock);
     
    19942005
    19952006    if (m_finallyBlock) {
     2007        RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
     2008       
    19962009        generator.popFinallyContext();
    19972010
     
    20032016
    20042017        // Uncaught exception path: invoke the finally block, then re-throw the exception.
    2005         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
    2006         RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
     2018        RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
    20072019        generator.emitNode(dst, m_finallyBlock);
    20082020        generator.emitThrow(tempExceptionRegister.get());
Note: See TracChangeset for help on using the changeset viewer.