Changeset 185083 in webkit


Ignore:
Timestamp:
Jun 1, 2015 4:22:22 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Add the ability to tell between Catch and Finally blocks.
https://bugs.webkit.org/show_bug.cgi?id=145524

Reviewed by Michael Saboff.

... and also SynthesizedFinally blocks too. A SynthesizedFinally block
is a finally block that is synthesized by the bytecode generator but
does not actually correspond to any exception handling construct at the
JS source code level. An example of this is the "for ... of" statement
where it needs to do some "final" clean up before passing on the
exception.

Manually tested by inspecting the bytecode dump of functions with
try-catch-finally blocks as well as for of statements which have
synthesized finally blocks. The bytecode dumps contains the exception
handlers table which has these blocks labelled with their newly added
types. No automatic test because this type info is not visible to JS
code.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/HandlerInfo.h:

(JSC::HandlerInfoBase::type):
(JSC::HandlerInfoBase::setType):
(JSC::HandlerInfoBase::typeName):
(JSC::HandlerInfoBase::isCatchHandler):
(JSC::UnlinkedHandlerInfo::UnlinkedHandlerInfo):
(JSC::HandlerInfo::initialize):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::pushTry):
(JSC::BytecodeGenerator::popTryAndEmitCatch):
(JSC::BytecodeGenerator::emitEnumeration):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::emitThrow):

  • bytecompiler/NodesCodegen.cpp:

(JSC::TryNode::emitBytecode):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r185067 r185083  
     12015-06-01  Mark Lam  <mark.lam@apple.com>
     2
     3        Add the ability to tell between Catch and Finally blocks.
     4        https://bugs.webkit.org/show_bug.cgi?id=145524
     5
     6        Reviewed by Michael Saboff.
     7
     8        ... and also SynthesizedFinally blocks too.  A SynthesizedFinally block
     9        is a finally block that is synthesized by the bytecode generator but
     10        does not actually correspond to any exception handling construct at the
     11        JS source code level.  An example of this is the "for ... of" statement
     12        where it needs to do some "final" clean up before passing on the
     13        exception.
     14
     15        Manually tested by inspecting the bytecode dump of functions with
     16        try-catch-finally blocks as well as for of statements which have
     17        synthesized finally blocks.  The bytecode dumps contains the exception
     18        handlers table which has these blocks labelled with their newly added
     19        types.  No automatic test because this type info is not visible to JS
     20        code.
     21
     22        * bytecode/CodeBlock.cpp:
     23        (JSC::CodeBlock::dumpBytecode):
     24        * bytecode/HandlerInfo.h:
     25        (JSC::HandlerInfoBase::type):
     26        (JSC::HandlerInfoBase::setType):
     27        (JSC::HandlerInfoBase::typeName):
     28        (JSC::HandlerInfoBase::isCatchHandler):
     29        (JSC::UnlinkedHandlerInfo::UnlinkedHandlerInfo):
     30        (JSC::HandlerInfo::initialize):
     31        * bytecompiler/BytecodeGenerator.cpp:
     32        (JSC::BytecodeGenerator::generate):
     33        (JSC::BytecodeGenerator::pushTry):
     34        (JSC::BytecodeGenerator::popTryAndEmitCatch):
     35        (JSC::BytecodeGenerator::emitEnumeration):
     36        * bytecompiler/BytecodeGenerator.h:
     37        (JSC::BytecodeGenerator::emitThrow):
     38        * bytecompiler/NodesCodegen.cpp:
     39        (JSC::TryNode::emitBytecode):
     40
    1412015-05-29  Geoffrey Garen  <ggaren@apple.com>
    242
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r185063 r185083  
    656656        do {
    657657            HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
    658             out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] depth: [%4d] }\n",
    659                 i + 1, handler.start, handler.end, handler.target, handler.scopeDepth);
     658            out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] depth: [%4d] } %s\n",
     659                i + 1, handler.start, handler.end, handler.target, handler.scopeDepth, handler.typeName());
    660660            ++i;
    661661        } while (i < m_rareData->m_exceptionHandlers.size());
  • trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h

    r185063 r185083  
    3131namespace JSC {
    3232
     33enum class HandlerType {
     34    Illegal = 0,
     35    Catch = 1,
     36    Finally = 2,
     37    SynthesizedFinally = 3
     38};
     39
    3340struct HandlerInfoBase {
     41    HandlerType type() const { return static_cast<HandlerType>(typeBits); }
     42    void setType(HandlerType type) { typeBits = static_cast<uint32_t>(type); }
     43   
     44    const char* typeName()
     45    {
     46        switch (type()) {
     47        case HandlerType::Catch:
     48            return "catch";
     49        case HandlerType::Finally:
     50            return "finally";
     51        case HandlerType::SynthesizedFinally:
     52            return "synthesized finally";
     53        default:
     54            ASSERT_NOT_REACHED();
     55        }
     56        return nullptr;
     57    }
     58   
     59    bool isCatchHandler() const { return type() == HandlerType::Catch; }
     60   
    3461    uint32_t start;
    3562    uint32_t end;
    3663    uint32_t target;
    37     uint32_t scopeDepth;
     64    uint32_t scopeDepth : 30;
     65    uint32_t typeBits : 2; // HandlerType
    3866};
    3967
    4068struct UnlinkedHandlerInfo : public HandlerInfoBase {
    41     UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, uint32_t scopeDepth)
     69    UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, uint32_t scopeDepth, HandlerType handlerType)
    4270    {
    4371        this->start = start;
     
    4573        this->target = target;
    4674        this->scopeDepth = scopeDepth;
     75        setType(handlerType);
     76        ASSERT(type() == handlerType);
    4777    }
    4878};
     
    5585        target = unlinkedInfo.target;
    5686        scopeDepth = unlinkedInfo.scopeDepth + nonLocalScopeDepth;
     87        typeBits = unlinkedInfo.typeBits;
    5788    }
    5889
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r185022 r185083  
    130130       
    131131        ASSERT(range.tryData->targetScopeDepth != UINT_MAX);
     132        ASSERT(range.tryData->handlerType != HandlerType::Illegal);
    132133        UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
    133             static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->targetScopeDepth);
     134            static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->targetScopeDepth,
     135            range.tryData->handlerType);
    134136        m_codeBlock->addExceptionHandler(info);
    135137    }
     
    25142516    tryData.target = newLabel();
    25152517    tryData.targetScopeDepth = UINT_MAX;
     2518    tryData.handlerType = HandlerType::Illegal;
    25162519    m_tryData.append(tryData);
    25172520    TryData* result = &m_tryData.last();
     
    25262529}
    25272530
    2528 RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* targetRegister, Label* end)
     2531RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* targetRegister, Label* end, HandlerType handlerType)
    25292532{
    25302533    m_usesExceptions = true;
     
    25412544    emitLabel(tryRange.tryData->target.get());
    25422545    tryRange.tryData->targetScopeDepth = m_localScopeDepth;
     2546    tryRange.tryData->handlerType = handlerType;
    25432547
    25442548    emitOpcode(op_catch);
     
    27572761        {
    27582762            RefPtr<Label> catchHere = emitLabel(newLabel().get());
    2759             RefPtr<RegisterID> exceptionRegister = popTryAndEmitCatch(tryData, newTemporary(), catchHere.get());
     2763            RefPtr<RegisterID> exceptionRegister = popTryAndEmitCatch(tryData, newTemporary(), catchHere.get(), HandlerType::SynthesizedFinally);
    27602764            RefPtr<Label> catchDone = newLabel();
    27612765
     
    27752779
    27762780            // Absorb exception.
    2777             popTryAndEmitCatch(returnCallTryData, newTemporary(), catchDone.get());
     2781            popTryAndEmitCatch(returnCallTryData, newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally);
    27782782            emitThrow(exceptionRegister.get());
    27792783        }
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r184828 r185083  
    176176        RefPtr<Label> target;
    177177        unsigned targetScopeDepth;
     178        HandlerType handlerType;
    178179    };
    179180
     
    553554        TryData* pushTry(Label* start);
    554555        // End a try block. 'end' must have been emitted.
    555         RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end);
     556        RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end, HandlerType);
    556557
    557558        void emitThrow(RegisterID* exc)
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r184859 r185083  
    28822882        // Uncaught exception path: the catch block.
    28832883        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
    2884         RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
     2884        RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get(), HandlerType::Catch);
    28852885       
    28862886        if (m_finallyBlock) {
     
    29132913
    29142914        // Uncaught exception path: invoke the finally block, then re-throw the exception.
    2915         RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
     2915        RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get(), HandlerType::Finally);
    29162916        generator.emitProfileControlFlow(finallyStartOffset);
    29172917        generator.emitNode(dst, m_finallyBlock);
Note: See TracChangeset for help on using the changeset viewer.