Title: [185083] trunk/Source/_javascript_Core
Revision
185083
Author
mark....@apple.com
Date
2015-06-01 16:22:22 -0700 (Mon, 01 Jun 2015)

Log 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):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (185082 => 185083)


--- trunk/Source/_javascript_Core/ChangeLog	2015-06-01 22:46:37 UTC (rev 185082)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-06-01 23:22:22 UTC (rev 185083)
@@ -1,3 +1,43 @@
+2015-06-01  Mark Lam  <mark....@apple.com>
+
+        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):
+
 2015-05-29  Geoffrey Garen  <gga...@apple.com>
 
         REGRESSION: These sorting idioms used by Peacekeeper and Browsermark are ~20X slower

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (185082 => 185083)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2015-06-01 22:46:37 UTC (rev 185082)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2015-06-01 23:22:22 UTC (rev 185083)
@@ -655,8 +655,8 @@
         unsigned i = 0;
         do {
             HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
-            out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] depth: [%4d] }\n",
-                i + 1, handler.start, handler.end, handler.target, handler.scopeDepth);
+            out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] depth: [%4d] } %s\n",
+                i + 1, handler.start, handler.end, handler.target, handler.scopeDepth, handler.typeName());
             ++i;
         } while (i < m_rareData->m_exceptionHandlers.size());
     }

Modified: trunk/Source/_javascript_Core/bytecode/HandlerInfo.h (185082 => 185083)


--- trunk/Source/_javascript_Core/bytecode/HandlerInfo.h	2015-06-01 22:46:37 UTC (rev 185082)
+++ trunk/Source/_javascript_Core/bytecode/HandlerInfo.h	2015-06-01 23:22:22 UTC (rev 185083)
@@ -30,20 +30,50 @@
 
 namespace JSC {
 
+enum class HandlerType {
+    Illegal = 0,
+    Catch = 1,
+    Finally = 2,
+    SynthesizedFinally = 3
+};
+
 struct HandlerInfoBase {
+    HandlerType type() const { return static_cast<HandlerType>(typeBits); }
+    void setType(HandlerType type) { typeBits = static_cast<uint32_t>(type); }
+    
+    const char* typeName()
+    {
+        switch (type()) {
+        case HandlerType::Catch:
+            return "catch";
+        case HandlerType::Finally:
+            return "finally";
+        case HandlerType::SynthesizedFinally:
+            return "synthesized finally";
+        default:
+            ASSERT_NOT_REACHED();
+        }
+        return nullptr;
+    }
+    
+    bool isCatchHandler() const { return type() == HandlerType::Catch; }
+    
     uint32_t start;
     uint32_t end;
     uint32_t target;
-    uint32_t scopeDepth;
+    uint32_t scopeDepth : 30;
+    uint32_t typeBits : 2; // HandlerType
 };
 
 struct UnlinkedHandlerInfo : public HandlerInfoBase {
-    UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, uint32_t scopeDepth)
+    UnlinkedHandlerInfo(uint32_t start, uint32_t end, uint32_t target, uint32_t scopeDepth, HandlerType handlerType)
     {
         this->start = start;
         this->end = end;
         this->target = target;
         this->scopeDepth = scopeDepth;
+        setType(handlerType);
+        ASSERT(type() == handlerType);
     }
 };
 
@@ -54,6 +84,7 @@
         end = unlinkedInfo.end;
         target = unlinkedInfo.target;
         scopeDepth = unlinkedInfo.scopeDepth + nonLocalScopeDepth;
+        typeBits = unlinkedInfo.typeBits;
     }
 
 #if ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (185082 => 185083)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-06-01 22:46:37 UTC (rev 185082)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-06-01 23:22:22 UTC (rev 185083)
@@ -129,8 +129,10 @@
             continue;
         
         ASSERT(range.tryData->targetScopeDepth != UINT_MAX);
+        ASSERT(range.tryData->handlerType != HandlerType::Illegal);
         UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
-            static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->targetScopeDepth);
+            static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->targetScopeDepth,
+            range.tryData->handlerType);
         m_codeBlock->addExceptionHandler(info);
     }
     
@@ -2513,6 +2515,7 @@
     TryData tryData;
     tryData.target = newLabel();
     tryData.targetScopeDepth = UINT_MAX;
+    tryData.handlerType = HandlerType::Illegal;
     m_tryData.append(tryData);
     TryData* result = &m_tryData.last();
     
@@ -2525,7 +2528,7 @@
     return result;
 }
 
-RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* targetRegister, Label* end)
+RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* targetRegister, Label* end, HandlerType handlerType)
 {
     m_usesExceptions = true;
     
@@ -2540,6 +2543,7 @@
     
     emitLabel(tryRange.tryData->target.get());
     tryRange.tryData->targetScopeDepth = m_localScopeDepth;
+    tryRange.tryData->handlerType = handlerType;
 
     emitOpcode(op_catch);
     instructions().append(targetRegister->index());
@@ -2756,7 +2760,7 @@
         // IteratorClose sequence for throw-ed control flow.
         {
             RefPtr<Label> catchHere = emitLabel(newLabel().get());
-            RefPtr<RegisterID> exceptionRegister = popTryAndEmitCatch(tryData, newTemporary(), catchHere.get());
+            RefPtr<RegisterID> exceptionRegister = popTryAndEmitCatch(tryData, newTemporary(), catchHere.get(), HandlerType::SynthesizedFinally);
             RefPtr<Label> catchDone = newLabel();
 
             RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
@@ -2774,7 +2778,7 @@
             emitThrow(exceptionRegister.get());
 
             // Absorb exception.
-            popTryAndEmitCatch(returnCallTryData, newTemporary(), catchDone.get());
+            popTryAndEmitCatch(returnCallTryData, newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally);
             emitThrow(exceptionRegister.get());
         }
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (185082 => 185083)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-06-01 22:46:37 UTC (rev 185082)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-06-01 23:22:22 UTC (rev 185083)
@@ -175,6 +175,7 @@
     struct TryData {
         RefPtr<Label> target;
         unsigned targetScopeDepth;
+        HandlerType handlerType;
     };
 
     struct TryContext {
@@ -552,7 +553,7 @@
         // Start a try block. 'start' must have been emitted.
         TryData* pushTry(Label* start);
         // End a try block. 'end' must have been emitted.
-        RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end);
+        RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end, HandlerType);
 
         void emitThrow(RegisterID* exc)
         { 

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (185082 => 185083)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-06-01 22:46:37 UTC (rev 185082)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-06-01 23:22:22 UTC (rev 185083)
@@ -2881,7 +2881,7 @@
 
         // Uncaught exception path: the catch block.
         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
-        RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
+        RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get(), HandlerType::Catch);
         
         if (m_finallyBlock) {
             // If the catch block throws an exception and we have a finally block, then the finally
@@ -2912,7 +2912,7 @@
         generator.emitJump(finallyEndLabel.get());
 
         // Uncaught exception path: invoke the finally block, then re-throw the exception.
-        RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
+        RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get(), HandlerType::Finally);
         generator.emitProfileControlFlow(finallyStartOffset);
         generator.emitNode(dst, m_finallyBlock);
         generator.emitThrow(tempExceptionRegister.get());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to