Title: [210007] trunk/Source/_javascript_Core
Revision
210007
Author
mark....@apple.com
Date
2016-12-19 17:48:52 -0800 (Mon, 19 Dec 2016)

Log Message

Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 1: Rollout r209974.
https://bugs.webkit.org/show_bug.cgi?id=166049

Not reviewed.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitEnumeration):
(JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded):
(JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded):
(JSC::BytecodeGenerator::emitFinallyCompletion):
(JSC::BytecodeGenerator::allocateFinallyRegisters):
(JSC::BytecodeGenerator::releaseFinallyRegisters):
(JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf):
(JSC::BytecodeGenerator::allocateCompletionRecordRegisters): Deleted.
(JSC::BytecodeGenerator::releaseCompletionRecordRegisters): Deleted.
(JSC::BytecodeGenerator::emitJumpIfCompletionType): Deleted.
* bytecompiler/BytecodeGenerator.h:
(JSC::FinallyJump::FinallyJump):
(JSC::FinallyContext::registerJump):
(JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope):
(JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope):
(JSC::BytecodeGenerator::finallyActionRegister):
(JSC::BytecodeGenerator::finallyReturnValueRegister):
(JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion):
(JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion):
(JSC::BytecodeGenerator::emitSetFinallyActionToJumpID):
(JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister):
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion):
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump):
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion):
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion):
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion):
(JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow):
(JSC::BytecodeGenerator::bytecodeOffsetToJumpID):
(JSC::bytecodeOffsetToJumpID): Deleted.
(JSC::BytecodeGenerator::CompletionRecordScope::CompletionRecordScope): Deleted.
(JSC::BytecodeGenerator::CompletionRecordScope::~CompletionRecordScope): Deleted.
(JSC::BytecodeGenerator::completionTypeRegister): Deleted.
(JSC::BytecodeGenerator::completionValueRegister): Deleted.
(JSC::BytecodeGenerator::emitSetCompletionType): Deleted.
(JSC::BytecodeGenerator::emitSetCompletionValue): Deleted.
* bytecompiler/NodesCodegen.cpp:
(JSC::TryNode::emitBytecode):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (210006 => 210007)


--- trunk/Source/_javascript_Core/ChangeLog	2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-12-20 01:48:52 UTC (rev 210007)
@@ -1,3 +1,49 @@
+2016-12-19  Mark Lam  <mark....@apple.com>
+
+        Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 1: Rollout r209974.
+        https://bugs.webkit.org/show_bug.cgi?id=166049
+
+        Not reviewed.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitEnumeration):
+        (JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded):
+        (JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded):
+        (JSC::BytecodeGenerator::emitFinallyCompletion):
+        (JSC::BytecodeGenerator::allocateFinallyRegisters):
+        (JSC::BytecodeGenerator::releaseFinallyRegisters):
+        (JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf):
+        (JSC::BytecodeGenerator::allocateCompletionRecordRegisters): Deleted.
+        (JSC::BytecodeGenerator::releaseCompletionRecordRegisters): Deleted.
+        (JSC::BytecodeGenerator::emitJumpIfCompletionType): Deleted.
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::FinallyJump::FinallyJump):
+        (JSC::FinallyContext::registerJump):
+        (JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope):
+        (JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope):
+        (JSC::BytecodeGenerator::finallyActionRegister):
+        (JSC::BytecodeGenerator::finallyReturnValueRegister):
+        (JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion):
+        (JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion):
+        (JSC::BytecodeGenerator::emitSetFinallyActionToJumpID):
+        (JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister):
+        (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion):
+        (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump):
+        (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion):
+        (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion):
+        (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion):
+        (JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow):
+        (JSC::BytecodeGenerator::bytecodeOffsetToJumpID):
+        (JSC::bytecodeOffsetToJumpID): Deleted.
+        (JSC::BytecodeGenerator::CompletionRecordScope::CompletionRecordScope): Deleted.
+        (JSC::BytecodeGenerator::CompletionRecordScope::~CompletionRecordScope): Deleted.
+        (JSC::BytecodeGenerator::completionTypeRegister): Deleted.
+        (JSC::BytecodeGenerator::completionValueRegister): Deleted.
+        (JSC::BytecodeGenerator::emitSetCompletionType): Deleted.
+        (JSC::BytecodeGenerator::emitSetCompletionValue): Deleted.
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::TryNode::emitBytecode):
+
 2016-12-19  Joseph Pecoraro  <pecor...@apple.com>
 
         Web Inspector: Assertion seen in InspectorDebuggerAgent::refAsyncCallData with Inspector open

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (210006 => 210007)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-12-20 01:48:52 UTC (rev 210007)
@@ -4126,7 +4126,7 @@
 
 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
 {
-    CompletionRecordScope completionRecordScope(*this);
+    FinallyRegistersScope finallyRegistersScope(*this);
 
     RefPtr<RegisterID> subject = newTemporary();
     emitNode(subject.get(), subjectNode);
@@ -4169,19 +4169,11 @@
             emitLabel(finallyViaThrowLabel.get());
             popTry(tryData, finallyViaThrowLabel.get());
 
-            RefPtr<Label> finallyBodyLabel = newLabel();
-            RefPtr<RegisterID> finallyExceptionRegister = newTemporary();
             RegisterID* unused = newTemporary();
+            emitCatch(finallyActionRegister(), unused);
+            // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
 
-            emitCatch(completionValueRegister(), unused);
-            emitSetCompletionType(CompletionType::Throw);
-            emitMove(finallyExceptionRegister.get(), completionValueRegister());
-            emitJump(finallyBodyLabel.get());
-
             emitLabel(finallyLabel.get());
-            emitMoveEmptyValue(finallyExceptionRegister.get());
-
-            emitLabel(finallyBodyLabel.get());
             restoreScopeRegister();
 
             RefPtr<Label> finallyDone = newLabel();
@@ -4189,6 +4181,9 @@
             RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
             emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get());
 
+            RefPtr<RegisterID> originalFinallyActionRegister = newTemporary();
+            emitMove(originalFinallyActionRegister.get(), finallyActionRegister());
+
             RefPtr<Label> returnCallTryStart = newLabel();
             emitLabel(returnCallTryStart.get());
             TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
@@ -4214,16 +4209,14 @@
                 RefPtr<RegisterID> exceptionRegister = newTemporary();
                 RegisterID* unused = newTemporary();
                 emitCatch(exceptionRegister.get(), unused);
-                // Since this is a synthesized catch block and we're guaranteed to never need
-                // to resolve any symbols from the scope, we can skip restoring the scope
-                // register here.
+                restoreScopeRegister();
 
                 RefPtr<Label> throwLabel = newLabel();
-                emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyExceptionRegister.get()), throwLabel.get());
-                emitMove(exceptionRegister.get(), finallyExceptionRegister.get());
+                emitJumpIfCompletionTypeIsThrow(originalFinallyActionRegister.get(), throwLabel.get());
+                emitMove(originalFinallyActionRegister.get(), exceptionRegister.get());
 
                 emitLabel(throwLabel.get());
-                emitThrow(exceptionRegister.get());
+                emitThrow(originalFinallyActionRegister.get());
 
                 emitLabel(endCatchLabel.get());
             }
@@ -4826,11 +4819,11 @@
     if (!outermostFinallyContext)
         return false; // No finallys to thread through.
 
-    auto jumpID = bytecodeOffsetToJumpID(instructions().size());
+    int jumpID = bytecodeOffsetToJumpID(instructions().size());
     int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);
     outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget);
 
-    emitSetCompletionType(jumpID);
+    emitSetFinallyActionToJumpID(jumpID);
     emitJump(innermostFinallyContext->finallyLabel());
     return true; // We'll be jumping to a finally block.
 }
@@ -4856,8 +4849,8 @@
     if (!innermostFinallyContext)
         return false; // No finallys to thread through.
 
-    emitSetCompletionType(CompletionType::Return);
-    emitSetCompletionValue(returnRegister);
+    emitSetFinallyActionToReturnCompletion();
+    emitSetFinallyReturnValueRegister(returnRegister);
     emitJump(innermostFinallyContext->finallyLabel());
     return true; // We'll be jumping to a finally block.
 }
@@ -4864,7 +4857,9 @@
 
 void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, Label* normalCompletionLabel)
 {
-    emitJumpIfCompletionType(op_stricteq, CompletionType::Normal, normalCompletionLabel);
+    // FIXME: switch the finallyActionRegister to only store int values for all CompletionTypes. This is more optimal for JIT type speculation.
+    // https://bugs.webkit.org/show_bug.cgi?id=165979
+    emitJumpIfFinallyActionIsNormalCompletion(normalCompletionLabel);
 
     if (context.numberOfBreaksOrContinues() || context.handlesReturns()) {
         FinallyContext* outerContext = context.outerContext();
@@ -4874,10 +4869,10 @@
             for (size_t i = 0; i < numberOfJumps; i++) {
                 RefPtr<Label> nextLabel = newLabel();
                 auto& jump = context.jumps(i);
-                emitJumpIfCompletionType(op_nstricteq, jump.jumpID, nextLabel.get());
+                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
 
                 restoreScopeRegister(jump.targetLexicalScopeIndex);
-                emitSetCompletionType(CompletionType::Normal);
+                emitSetFinallyActionToNormalCompletion();
                 emitJump(jump.targetLabel.get());
 
                 emitLabel(nextLabel.get());
@@ -4885,7 +4880,7 @@
 
             bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() > numberOfJumps;
             if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns())
-                emitJumpIfCompletionType(op_nstricteq, CompletionType::Throw, outerContext->finallyLabel());
+                emitJumpIfFinallyActionIsNotThrowCompletion(outerContext->finallyLabel());
 
         } else {
             // We are the outermost finally.
@@ -4895,10 +4890,10 @@
             for (size_t i = 0; i < numberOfJumps; i++) {
                 RefPtr<Label> nextLabel = newLabel();
                 auto& jump = context.jumps(i);
-                emitJumpIfCompletionType(op_nstricteq, jump.jumpID, nextLabel.get());
+                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
 
                 restoreScopeRegister(jump.targetLexicalScopeIndex);
-                emitSetCompletionType(CompletionType::Normal);
+                emitSetFinallyActionToNormalCompletion();
                 emitJump(jump.targetLabel.get());
 
                 emitLabel(nextLabel.get());
@@ -4906,46 +4901,46 @@
 
             if (context.handlesReturns()) {
                 RefPtr<Label> notReturnLabel = newLabel();
-                emitJumpIfCompletionType(op_nstricteq, CompletionType::Return, notReturnLabel.get());
+                emitJumpIfFinallyActionIsNotReturnCompletion(notReturnLabel.get());
 
                 emitWillLeaveCallFrameDebugHook();
-                emitReturn(completionValueRegister(), ReturnFrom::Finally);
+                emitReturn(finallyReturnValueRegister(), ReturnFrom::Finally);
                 
                 emitLabel(notReturnLabel.get());
             }
         }
     }
-    emitThrow(completionValueRegister());
+    emitThrow(finallyActionRegister());
 }
 
-bool BytecodeGenerator::allocateCompletionRecordRegisters()
+bool BytecodeGenerator::allocateFinallyRegisters()
 {
-    if (m_completionTypeRegister)
+    if (m_finallyActionRegister)
         return false;
 
-    ASSERT(!m_completionValueRegister);
-    m_completionTypeRegister = newTemporary();
-    m_completionValueRegister = newTemporary();
+    ASSERT(!m_finallyReturnValueRegister);
+    m_finallyActionRegister = newTemporary();
+    m_finallyReturnValueRegister = newTemporary();
 
-    emitSetCompletionType(CompletionType::Normal);
-    emitMoveEmptyValue(m_completionValueRegister.get());
+    emitSetFinallyActionToNormalCompletion();
+    emitMoveEmptyValue(m_finallyReturnValueRegister.get());
     return true;
 }
 
-void BytecodeGenerator::releaseCompletionRecordRegisters()
+void BytecodeGenerator::releaseFinallyRegisters()
 {
-    ASSERT(m_completionTypeRegister && m_completionValueRegister);
-    m_completionTypeRegister = nullptr;
-    m_completionValueRegister = nullptr;
+    ASSERT(m_finallyActionRegister && m_finallyReturnValueRegister);
+    m_finallyActionRegister = nullptr;
+    m_finallyReturnValueRegister = nullptr;
 }
 
-void BytecodeGenerator::emitJumpIfCompletionType(OpcodeID compareOpcode, CompletionType type, Label* jumpTarget)
+void BytecodeGenerator::emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget)
 {
     RefPtr<RegisterID> tempRegister = newTemporary();
-    RegisterID* valueConstant = addConstantValue(JSValue(static_cast<int>(type)));
+    RegisterID* valueConstant = addConstantValue(JSValue(value));
     OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType());
 
-    auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, completionTypeRegister(), operandTypes);
+    auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, finallyActionRegister(), operandTypes);
     emitJumpIfTrue(equivalenceResult, jumpTarget);
 }
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (210006 => 210007)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-12-20 01:48:52 UTC (rev 210007)
@@ -80,41 +80,15 @@
         unsigned m_padding;
     };
 
-    // https://tc39.github.io/ecma262/#sec-completion-record-specification-type
-    //
-    // For the Break and Continue cases, instead of using the Break and Continue enum values
-    // below, we use the unique jumpID of the break and continue statement as the encoding
-    // for the CompletionType value. emitFinallyCompletion() uses this jumpID value later
-    // to determine the appropriate jump target to jump to after executing the relevant finally
-    // blocks. The jumpID is computed as:
-    //     jumpID = bytecodeOffset (of the break/continue node) + CompletionType::NumberOfTypes.
-    // Hence, there won't be any collision between jumpIDs and CompletionType enums.
-    enum class CompletionType : int {
-        Normal,
-        Break,
-        Continue,
-        Return,
-        Throw,
-        
-        NumberOfTypes
-    };
-
-    inline CompletionType bytecodeOffsetToJumpID(unsigned offset)
-    {
-        int jumpIDAsInt = offset + static_cast<int>(CompletionType::NumberOfTypes);
-        ASSERT(jumpIDAsInt >= static_cast<int>(CompletionType::NumberOfTypes));
-        return static_cast<CompletionType>(jumpIDAsInt);
-    }
-
     struct FinallyJump {
-        FinallyJump(CompletionType jumpID, int targetLexicalScopeIndex, Label* targetLabel)
+        FinallyJump(int jumpID, int targetLexicalScopeIndex, Label* targetLabel)
             : jumpID(jumpID)
             , targetLexicalScopeIndex(targetLexicalScopeIndex)
             , targetLabel(targetLabel)
         { }
 
-        CompletionType jumpID;
-        int targetLexicalScopeIndex;
+        int jumpID { 0 };
+        int targetLexicalScopeIndex { 0 };
         RefPtr<Label> targetLabel;
     };
 
@@ -142,7 +116,7 @@
         bool handlesReturns() const { return m_handlesReturns; }
         void setHandlesReturns() { m_handlesReturns = true; }
 
-        void registerJump(CompletionType jumpID, int lexicalScopeIndex, Label* targetLabel)
+        void registerJump(int jumpID, int lexicalScopeIndex, Label* targetLabel)
         {
             if (!m_jumps)
                 m_jumps = std::make_unique<Vector<FinallyJump>>();
@@ -801,18 +775,18 @@
         void emitDebugHook(ExpressionNode*);
         void emitWillLeaveCallFrameDebugHook();
 
-        class CompletionRecordScope {
+        class FinallyRegistersScope {
         public:
-            CompletionRecordScope(BytecodeGenerator& generator, bool needCompletionRecordRegisters = true)
+            FinallyRegistersScope(BytecodeGenerator& generator, bool needFinallyRegisters = true)
                 : m_generator(generator)
             {
-                if (needCompletionRecordRegisters && m_generator.allocateCompletionRecordRegisters())
+                if (needFinallyRegisters && m_generator.allocateFinallyRegisters())
                     m_needToReleaseOnDestruction = true;
             }
-            ~CompletionRecordScope()
+            ~FinallyRegistersScope()
             {
                 if (m_needToReleaseOnDestruction)
-                    m_generator.releaseCompletionRecordRegisters();
+                    m_generator.releaseFinallyRegisters();
             }
 
         private:
@@ -820,36 +794,79 @@
             bool m_needToReleaseOnDestruction { false };
         };
 
-        RegisterID* completionTypeRegister() const
+        RegisterID* finallyActionRegister() const
         {
-            ASSERT(m_completionTypeRegister);
-            return m_completionTypeRegister.get();
+            ASSERT(m_finallyActionRegister);
+            return m_finallyActionRegister.get();
         }
-        RegisterID* completionValueRegister() const
+        RegisterID* finallyReturnValueRegister() const
         {
-            ASSERT(m_completionValueRegister);
-            return m_completionValueRegister.get();
+            ASSERT(m_finallyReturnValueRegister);
+            return m_finallyReturnValueRegister.get();
         }
 
-        void emitSetCompletionType(CompletionType type)
+        void emitSetFinallyActionToNormalCompletion()
         {
-            emitLoad(completionTypeRegister(), JSValue(static_cast<int>(type)));
+            emitMoveEmptyValue(m_finallyActionRegister.get());
         }
-        void emitSetCompletionValue(RegisterID* reg)
+        void emitSetFinallyActionToReturnCompletion()
         {
-            emitMove(completionValueRegister(), reg);
+            emitLoad(finallyActionRegister(), JSValue(static_cast<int>(CompletionType::Return)));
         }
+        void emitSetFinallyActionToJumpID(int jumpID)
+        {
+            emitLoad(finallyActionRegister(), JSValue(jumpID));
+        }
+        void emitSetFinallyReturnValueRegister(RegisterID* reg)
+        {
+            emitMove(finallyReturnValueRegister(), reg);
+        }
 
-        void emitJumpIfCompletionType(OpcodeID compareOpcode, CompletionType, Label* jumpTarget);
+        void emitJumpIfFinallyActionIsNormalCompletion(Label* jumpTarget)
+        {
+            emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyActionRegister()), jumpTarget);
+        }
 
+        void emitJumpIfFinallyActionIsNotJump(int jumpID, Label* jumpTarget)
+        {
+            emitCompareFinallyActionAndJumpIf(op_nstricteq, jumpID, jumpTarget);
+        }
+
+        void emitJumpIfFinallyActionIsReturnCompletion(Label* jumpTarget)
+        {
+            emitCompareFinallyActionAndJumpIf(op_stricteq, static_cast<int>(CompletionType::Return), jumpTarget);
+        }
+        void emitJumpIfFinallyActionIsNotReturnCompletion(Label* jumpTarget)
+        {
+            emitCompareFinallyActionAndJumpIf(op_nstricteq, static_cast<int>(CompletionType::Return), jumpTarget);
+        }
+
+        void emitJumpIfFinallyActionIsNotThrowCompletion(Label* jumpTarget)
+        {
+            emitJumpIfTrue(emitIsNumber(newTemporary(), finallyActionRegister()), jumpTarget);
+        }
+        void emitJumpIfCompletionTypeIsThrow(RegisterID* reg, Label* jumpTarget)
+        {
+            emitJumpIfFalse(emitIsNumber(newTemporary(), reg), jumpTarget);
+        }
+
         bool emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget);
         bool emitReturnViaFinallyIfNeeded(RegisterID* returnRegister);
         void emitFinallyCompletion(FinallyContext&, Label* normalCompletionLabel);
 
     private:
-        bool allocateCompletionRecordRegisters();
-        void releaseCompletionRecordRegisters();
+        void emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget);
 
+        int bytecodeOffsetToJumpID(unsigned offset)
+        {
+            int jumpID = offset + static_cast<int>(CompletionType::NumberOfTypes);
+            ASSERT(jumpID >= static_cast<int>(CompletionType::NumberOfTypes));
+            return jumpID;
+        }
+
+        bool allocateFinallyRegisters();
+        void releaseFinallyRegisters();
+
     public:
         FinallyContext* pushFinallyControlFlowScope(Label* finallyLabel);
         FinallyContext popFinallyControlFlowScope();
@@ -1083,9 +1100,33 @@
         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
         RegisterID* m_promiseCapabilityRegister { nullptr };
 
-        RefPtr<RegisterID> m_completionTypeRegister;
-        RefPtr<RegisterID> m_completionValueRegister;
+        // The spec at https://tc39.github.io/ecma262/#sec-completion-record-specification-type says
+        // that there are 5 types of completions. Conceptually, we'll set m_finallyActionRegister
+        // to one of these completion types. However, to optimize our implementation, we'll encode
+        // these type info as follows:
+        //
+        //     CompletionType::Normal   - m_finallyActionRegister is empty.
+        //     CompletionType::Break    - m_finallyActionRegister is an int JSValue jumpID.
+        //     CompletionType::Continue - m_finallyActionRegister is an int JSValue jumpID.
+        //     CompletionType::Return   - m_finallyActionRegister is the Return enum as an int JSValue.
+        //     CompletionType::Throw    - m_finallyActionRegister is the Exception object to rethrow.
+        //
+        // Hence, of the 5 completion types, only the CompletionType::Return enum value is used in
+        // our implementation. The rest are just provided for completeness.
 
+        enum class CompletionType : int {
+            Normal,
+            Break,
+            Continue,
+            Return,
+            Throw,
+
+            NumberOfTypes
+        };
+
+        RefPtr<RegisterID> m_finallyActionRegister;
+        RefPtr<RegisterID> m_finallyReturnValueRegister;
+
         FinallyContext* m_currentFinallyContext { nullptr };
 
         SegmentedVector<RegisterID*, 16> m_localRegistersForCalleeSaveRegisters;
@@ -1102,7 +1143,7 @@
         void pushLocalControlFlowScope();
         void popLocalControlFlowScope();
 
-        // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it.
+        // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 
         // https://bugs.webkit.org/show_bug.cgi?id=165980
         SegmentedVector<ControlFlowScope, 16> m_controlFlowScopeStack;
         Vector<SwitchInfo> m_switchContextStack;

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (210006 => 210007)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-12-20 01:48:52 UTC (rev 210007)
@@ -3287,7 +3287,7 @@
     // optimizer knows they may be jumped to from anywhere.
 
     ASSERT(m_catchBlock || m_finallyBlock);
-    BytecodeGenerator::CompletionRecordScope completionRecordScope(generator, m_finallyBlock);
+    BytecodeGenerator::FinallyRegistersScope finallyRegistersScope(generator, m_finallyBlock);
 
     RefPtr<Label> catchLabel;
     RefPtr<Label> catchEndLabel;
@@ -3316,6 +3316,7 @@
 
     generator.emitNode(dst, m_tryBlock);
 
+    // The finallyActionRegister is an empty value by default, which implies CompletionType::Normal.
     if (m_finallyBlock)
         generator.emitJump(finallyLabel.get());
     else
@@ -3350,7 +3351,7 @@
         generator.emitPopCatchScope(m_lexicalVariables);
 
         if (m_finallyBlock) {
-            generator.emitSetCompletionType(CompletionType::Normal);
+            generator.emitSetFinallyActionToNormalCompletion();
             generator.emitJump(finallyLabel.get());
             generator.popTry(tryData, finallyViaThrowLabel.get());
         }
@@ -3365,8 +3366,8 @@
         // Entry to the finally block for CompletionType::Throw.
         generator.emitLabel(finallyViaThrowLabel.get());
         RegisterID* unused = generator.newTemporary();
-        generator.emitCatch(generator.completionValueRegister(), unused);
-        generator.emitSetCompletionType(CompletionType::Throw);
+        generator.emitCatch(generator.finallyActionRegister(), unused);
+        // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
 
         // Entry to the finally block for CompletionTypes other than Throw.
         generator.emitLabel(finallyLabel.get());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to