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());