Implement catch scope using lexical scoping constructs introduced with "let" scoping patch
https://bugs.webkit.org/show_bug.cgi?id=146979

Reviewed by Geoffrey Garen.

Now that BytecodeGenerator has a notion of local scope depth,
we can easily implement a catch scope that doesn't claim that
all variables are dynamically scoped. This means that functions
that use try/catch can have local variable resolution. This also
means that all functions that use try/catch don't have all
their variables marked as being captured.

Catch scopes now behave like a "let" scope (sans the TDZ logic) with a 
single variable. Catch scopes are now just JSLexicalEnvironments and the 
symbol table backing the catch scope knows that it corresponds to a catch scope.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::isCacheable):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::emitLoadGlobalObject):
(JSC::BytecodeGenerator::pushLexicalScope):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
(JSC::BytecodeGenerator::popLexicalScope):
(JSC::BytecodeGenerator::popLexicalScopeInternal):
(JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration):
(JSC::BytecodeGenerator::variable):
(JSC::BytecodeGenerator::resolveType):
(JSC::BytecodeGenerator::emitResolveScope):
(JSC::BytecodeGenerator::emitPopScope):
(JSC::BytecodeGenerator::emitPopWithScope):
(JSC::BytecodeGenerator::emitDebugHook):
(JSC::BytecodeGenerator::popScopedControlFlowContext):
(JSC::BytecodeGenerator::emitPushCatchScope):
(JSC::BytecodeGenerator::emitPopCatchScope):
(JSC::BytecodeGenerator::beginSwitch):
(JSC::BytecodeGenerator::emitPopWithOrCatchScope): Deleted.
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::lastOpcodeID):
* bytecompiler/NodesCodegen.cpp:
(JSC::AssignResolveNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::TryNode::emitBytecode):
* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::isCatchScope):
(JSC::DebuggerScope::isFunctionNameScope):
(JSC::DebuggerScope::isFunctionOrEvalScope):
(JSC::DebuggerScope::caughtValue):
* debugger/DebuggerScope.h:
* inspector/ScriptDebugServer.cpp:
(Inspector::ScriptDebugServer::exceptionOrCaughtValue):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_push_name_scope):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_push_name_scope):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createContinueStatement):
(JSC::ASTBuilder::createTryStatement):
* parser/NodeConstructors.h:
(JSC::ThrowNode::ThrowNode):
(JSC::TryNode::TryNode):
(JSC::FunctionParameters::FunctionParameters):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseTryStatement):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createBreakStatement):
(JSC::SyntaxChecker::createContinueStatement):
(JSC::SyntaxChecker::createTryStatement):
(JSC::SyntaxChecker::createSwitchStatement):
(JSC::SyntaxChecker::createWhileStatement):
(JSC::SyntaxChecker::createWithStatement):
* runtime/JSCatchScope.cpp:
* runtime/JSCatchScope.h:
(JSC::JSCatchScope::JSCatchScope): Deleted.
(JSC::JSCatchScope::create): Deleted.
(JSC::JSCatchScope::createStructure): Deleted.
* runtime/JSFunctionNameScope.h:
(JSC::JSFunctionNameScope::JSFunctionNameScope):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::withScopeStructure):
(JSC::JSGlobalObject::strictEvalActivationStructure):
(JSC::JSGlobalObject::activationStructure):
(JSC::JSGlobalObject::functionNameScopeStructure):
(JSC::JSGlobalObject::directArgumentsStructure):
(JSC::JSGlobalObject::scopedArgumentsStructure):
(JSC::JSGlobalObject::catchScopeStructure): Deleted.
* runtime/JSNameScope.cpp:
(JSC::JSNameScope::create):
(JSC::JSNameScope::toThis):
* runtime/JSNameScope.h:
* runtime/JSObject.cpp:
(JSC::JSObject::toThis):
(JSC::JSObject::isFunctionNameScopeObject):
(JSC::JSObject::isCatchScopeObject): Deleted.
* runtime/JSObject.h:
* runtime/JSScope.cpp:
(JSC::JSScope::collectVariablesUnderTDZ):
(JSC::JSScope::isLexicalScope):
(JSC::JSScope::isCatchScope):
(JSC::resolveModeName):
* runtime/JSScope.h:
* runtime/SymbolTable.cpp:
(JSC::SymbolTable::SymbolTable):
(JSC::SymbolTable::cloneScopePart):
* runtime/SymbolTable.h:
* tests/stress/const-semantics.js:
(.):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@187515 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index c365475..a273e40 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -490,7 +490,6 @@
     runtime/JSBoundFunction.cpp
     runtime/JSCJSValue.cpp
     runtime/JSCallee.cpp
-    runtime/JSCatchScope.cpp
     runtime/JSCell.cpp
     runtime/JSConsole.cpp
     runtime/JSDataView.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 6b5431c..c1a0597 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,127 @@
+2015-07-28  Saam barati  <saambarati1@gmail.com>
+
+        Implement catch scope using lexical scoping constructs introduced with "let" scoping patch
+        https://bugs.webkit.org/show_bug.cgi?id=146979
+
+        Reviewed by Geoffrey Garen.
+
+        Now that BytecodeGenerator has a notion of local scope depth,
+        we can easily implement a catch scope that doesn't claim that
+        all variables are dynamically scoped. This means that functions
+        that use try/catch can have local variable resolution. This also
+        means that all functions that use try/catch don't have all
+        their variables marked as being captured.
+
+        Catch scopes now behave like a "let" scope (sans the TDZ logic) with a 
+        single variable. Catch scopes are now just JSLexicalEnvironments and the 
+        symbol table backing the catch scope knows that it corresponds to a catch scope.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::isCacheable):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+        (JSC::BytecodeGenerator::emitLoadGlobalObject):
+        (JSC::BytecodeGenerator::pushLexicalScope):
+        (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+        (JSC::BytecodeGenerator::popLexicalScope):
+        (JSC::BytecodeGenerator::popLexicalScopeInternal):
+        (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration):
+        (JSC::BytecodeGenerator::variable):
+        (JSC::BytecodeGenerator::resolveType):
+        (JSC::BytecodeGenerator::emitResolveScope):
+        (JSC::BytecodeGenerator::emitPopScope):
+        (JSC::BytecodeGenerator::emitPopWithScope):
+        (JSC::BytecodeGenerator::emitDebugHook):
+        (JSC::BytecodeGenerator::popScopedControlFlowContext):
+        (JSC::BytecodeGenerator::emitPushCatchScope):
+        (JSC::BytecodeGenerator::emitPopCatchScope):
+        (JSC::BytecodeGenerator::beginSwitch):
+        (JSC::BytecodeGenerator::emitPopWithOrCatchScope): Deleted.
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::lastOpcodeID):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::AssignResolveNode::emitBytecode):
+        (JSC::WithNode::emitBytecode):
+        (JSC::TryNode::emitBytecode):
+        * debugger/DebuggerScope.cpp:
+        (JSC::DebuggerScope::isCatchScope):
+        (JSC::DebuggerScope::isFunctionNameScope):
+        (JSC::DebuggerScope::isFunctionOrEvalScope):
+        (JSC::DebuggerScope::caughtValue):
+        * debugger/DebuggerScope.h:
+        * inspector/ScriptDebugServer.cpp:
+        (Inspector::ScriptDebugServer::exceptionOrCaughtValue):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_push_name_scope):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_push_name_scope):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createContinueStatement):
+        (JSC::ASTBuilder::createTryStatement):
+        * parser/NodeConstructors.h:
+        (JSC::ThrowNode::ThrowNode):
+        (JSC::TryNode::TryNode):
+        (JSC::FunctionParameters::FunctionParameters):
+        * parser/Nodes.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseTryStatement):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createBreakStatement):
+        (JSC::SyntaxChecker::createContinueStatement):
+        (JSC::SyntaxChecker::createTryStatement):
+        (JSC::SyntaxChecker::createSwitchStatement):
+        (JSC::SyntaxChecker::createWhileStatement):
+        (JSC::SyntaxChecker::createWithStatement):
+        * runtime/JSCatchScope.cpp:
+        * runtime/JSCatchScope.h:
+        (JSC::JSCatchScope::JSCatchScope): Deleted.
+        (JSC::JSCatchScope::create): Deleted.
+        (JSC::JSCatchScope::createStructure): Deleted.
+        * runtime/JSFunctionNameScope.h:
+        (JSC::JSFunctionNameScope::JSFunctionNameScope):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::withScopeStructure):
+        (JSC::JSGlobalObject::strictEvalActivationStructure):
+        (JSC::JSGlobalObject::activationStructure):
+        (JSC::JSGlobalObject::functionNameScopeStructure):
+        (JSC::JSGlobalObject::directArgumentsStructure):
+        (JSC::JSGlobalObject::scopedArgumentsStructure):
+        (JSC::JSGlobalObject::catchScopeStructure): Deleted.
+        * runtime/JSNameScope.cpp:
+        (JSC::JSNameScope::create):
+        (JSC::JSNameScope::toThis):
+        * runtime/JSNameScope.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::toThis):
+        (JSC::JSObject::isFunctionNameScopeObject):
+        (JSC::JSObject::isCatchScopeObject): Deleted.
+        * runtime/JSObject.h:
+        * runtime/JSScope.cpp:
+        (JSC::JSScope::collectVariablesUnderTDZ):
+        (JSC::JSScope::isLexicalScope):
+        (JSC::JSScope::isCatchScope):
+        (JSC::resolveModeName):
+        * runtime/JSScope.h:
+        * runtime/SymbolTable.cpp:
+        (JSC::SymbolTable::SymbolTable):
+        (JSC::SymbolTable::cloneScopePart):
+        * runtime/SymbolTable.h:
+        * tests/stress/const-semantics.js:
+        (.):
+
 2015-07-28  Filip Pizlo  <fpizlo@apple.com>
 
         DFG::ArgumentsEliminationPhase has a redundant check for inserting CheckInBounds when converting GetByVal to GetStack in the inline non-varargs case
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
index 244ba19..a45ab66 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
@@ -745,7 +745,6 @@
     <ClCompile Include="..\runtime\JSBoundFunction.cpp" />
     <ClCompile Include="..\runtime\JSCJSValue.cpp" />
     <ClCompile Include="..\runtime\JSCallee.cpp" />
-    <ClCompile Include="..\runtime\JSCatchScope.cpp" />
     <ClCompile Include="..\runtime\JSCell.cpp" />
     <ClCompile Include="..\runtime\JSConsole.cpp" />
     <ClCompile Include="..\runtime\JSDataView.cpp" />
@@ -1557,7 +1556,6 @@
     <ClInclude Include="..\runtime\JSCJSValue.h" />
     <ClInclude Include="..\runtime\JSCJSValueInlines.h" />
     <ClInclude Include="..\runtime\JSCallee.h" />
-    <ClInclude Include="..\runtime\JSCatchScope.h" />
     <ClInclude Include="..\runtime\JSCell.h" />
     <ClInclude Include="..\runtime\JSConsole.h" />
     <ClInclude Include="..\runtime\JSDataView.h" />
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
index c5bd549..6ce3677 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
@@ -1771,7 +1771,6 @@
     <ClCompile Include="..\dfg\DFGPutStackSinkingPhase.cpp" />
     <ClCompile Include="..\ftl\FTLJSCallBase.cpp" />
     <ClCompile Include="..\ftl\FTLJSCallVarargs.cpp" />
-    <ClCompile Include="..\runtime\JSCatchScope.cpp" />
     <ClCompile Include="..\runtime\JSFunctionNameScope.cpp" />
     <ClCompile Include="..\jit\ExecutableAllocatorFixedVMPool.cpp">
       <Filter>jit</Filter>
@@ -4272,7 +4271,6 @@
     <ClInclude Include="..\dfg\DFGPutStackSinkingPhase.h" />
     <ClInclude Include="..\ftl\FTLJSCallBase.h" />
     <ClInclude Include="..\ftl\FTLJSCallVarargs.h" />
-    <ClInclude Include="..\runtime\JSCatchScope.h" />
     <ClInclude Include="..\runtime\JSFunctionNameScope.h" />
     <ClInclude Include="..\runtime\MathCommon.h" />
     <ClInclude Include="..\bytecode\BytecodeKills.h" />
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index b4acc194..699e7a6 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -610,8 +610,6 @@
 		0FD8A32A17D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD8A32217D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD8A32317D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp */; };
 		0FD8A32C17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD8A32417D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		0FD949821A97DB9600E28966 /* JSCatchScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */; };
-		0FD949831A97DB9600E28966 /* JSCatchScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FD949841A97DB9600E28966 /* JSFunctionNameScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD949801A97DB9600E28966 /* JSFunctionNameScope.cpp */; };
 		0FD949851A97DB9600E28966 /* JSFunctionNameScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD949811A97DB9600E28966 /* JSFunctionNameScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2372,8 +2370,6 @@
 		0FD8A32217D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGToFTLDeferredCompilationCallback.h; path = dfg/DFGToFTLDeferredCompilationCallback.h; sourceTree = "<group>"; };
 		0FD8A32317D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGToFTLForOSREntryDeferredCompilationCallback.cpp; path = dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp; sourceTree = "<group>"; };
 		0FD8A32417D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGToFTLForOSREntryDeferredCompilationCallback.h; path = dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h; sourceTree = "<group>"; };
-		0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCatchScope.cpp; sourceTree = "<group>"; };
-		0FD9497F1A97DB9600E28966 /* JSCatchScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCatchScope.h; sourceTree = "<group>"; };
 		0FD949801A97DB9600E28966 /* JSFunctionNameScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFunctionNameScope.cpp; sourceTree = "<group>"; };
 		0FD949811A97DB9600E28966 /* JSFunctionNameScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFunctionNameScope.h; sourceTree = "<group>"; };
 		0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLAbbreviatedTypes.h; path = ftl/FTLAbbreviatedTypes.h; sourceTree = "<group>"; };
@@ -4530,8 +4526,6 @@
 				86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
 				657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
 				657CF45719BF6662004ACBF2 /* JSCallee.h */,
-				0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */,
-				0FD9497F1A97DB9600E28966 /* JSCatchScope.h */,
 				BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
 				BC1167D80E19BCC9008066DD /* JSCell.h */,
 				0F97496F1687ADE200A4FF6A /* JSCellInlines.h */,
@@ -6292,7 +6286,6 @@
 				0F2B9CE719D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h in Headers */,
 				A7CA3AE817DA41AE006538AF /* JSWeakMap.h in Headers */,
 				A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */,
-				0FD949831A97DB9600E28966 /* JSCatchScope.h in Headers */,
 				A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */,
 				1442566215EDE98D0066A49B /* JSWithScope.h in Headers */,
 				86E3C619167BABEE006D760A /* JSWrapperMap.h in Headers */,
@@ -7435,7 +7428,6 @@
 				86E3C616167BABEE006D760A /* JSContext.mm in Sources */,
 				14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */,
 				70DC3E091B2DF2C700054299 /* IteratorPrototype.cpp in Sources */,
-				0FD949821A97DB9600E28966 /* JSCatchScope.cpp in Sources */,
 				A72028B61797601E0098028C /* JSCTestRunnerUtils.cpp in Sources */,
 				0F2B66EB17B6B5AB00A7AE3F /* JSDataView.cpp in Sources */,
 				0F2B66ED17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp in Sources */,
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 041ff08..8668394 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1457,7 +1457,7 @@
             int k0 = (++it)->u.operand;
             JSNameScope::Type scopeType = (JSNameScope::Type)(++it)->u.operand;
             printLocationAndOp(out, exec, location, it, "push_name_scope");
-            out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(r1).data(), constantName(k0).data(), (scopeType == JSNameScope::FunctionNameScope) ? "functionScope" : ((scopeType == JSNameScope::CatchScope) ? "catchScope" : "unknownScopeType"));
+            out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(r1).data(), constantName(k0).data(), (scopeType == JSNameScope::FunctionNameScope) ? "functionScope" : "unknownScopeType");
             break;
         }
         case op_create_lexical_environment: {
diff --git a/Source/JavaScriptCore/bytecode/EvalCodeCache.h b/Source/JavaScriptCore/bytecode/EvalCodeCache.h
index 3a02ef9..4d59093 100644
--- a/Source/JavaScriptCore/bytecode/EvalCodeCache.h
+++ b/Source/JavaScriptCore/bytecode/EvalCodeCache.h
@@ -81,7 +81,8 @@
             return !inStrictContext 
                 && evalSource.length() < Options::maximumEvalCacheableSourceLength() 
                 && scope->begin()->isVariableObject()
-                && !scope->isLexicalScope();
+                && !scope->isLexicalScope()
+                && !scope->isCatchScope();
         }
         static const int maxCacheEntries = 64;
 
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 7f31274..548ae44 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -578,7 +578,7 @@
         }
         
         // This implements step 25 of section 9.2.12.
-        pushLexicalScopeInternal(environment, true, nullptr);
+        pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope);
 
         RefPtr<RegisterID> temp = newTemporary();
         for (unsigned i = 0; i < parameters.size(); i++) {
@@ -1357,7 +1357,13 @@
     return m_globalObjectRegister;
 }
 
-void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+{
+    VariableEnvironment& environment = node->lexicalVariables();
+    pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope);
+}
+
+void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType)
 {
     if (!environment.size())
         return;
@@ -1366,11 +1372,19 @@
         environment.markAllVariablesAsCaptured();
 
     Strong<SymbolTable> symbolTable(*m_vm, SymbolTable::create(*m_vm));
-    symbolTable->setDoesCorrespondToLexicalScope();
+    switch (scopeType) {
+    case ScopeType::CatchScope:
+        symbolTable->setScopeType(SymbolTable::ScopeType::CatchScope);
+        break;
+    case ScopeType::LetConstScope:
+        symbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);
+        break;
+    }
+
     bool hasCapturedVariables = false;
     {
         ConcurrentJITLocker locker(symbolTable->m_lock);
-        for (auto entry : environment) {
+        for (auto& entry : environment) {
             ASSERT(entry.value.isLet() || entry.value.isConst());
             ASSERT(!entry.value.isVar());
             SymbolTableEntry symbolTableEntry = symbolTable->get(locker, entry.key.get());
@@ -1408,7 +1422,7 @@
         instructions().append(newScope->index());
         instructions().append(scopeRegister()->index());
         instructions().append(constantSymbolTable->index());
-        instructions().append(addConstantValue(jsTDZValue())->index());
+        instructions().append(addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined())->index());
 
         emitMove(scopeRegister(), newScope);
 
@@ -1416,31 +1430,34 @@
     }
 
     m_symbolTableStack.append(SymbolTableStackEntry{ symbolTable, newScope, false, symbolTableConstantIndex });
-    m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks));
-    // Prefill stack variables with the TDZ empty value.
-    // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
-    for (auto entry : environment) {
-        SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get());
-        ASSERT(!symbolTableEntry.isNull());
-        VarOffset offset = symbolTableEntry.varOffset();
-        if (offset.isScope()) {
-            ASSERT(newScope);
-            continue;
-        }
-        ASSERT(offset.isStack());
-        emitMoveEmptyValue(&registerFor(offset.stackOffset()));
-    }
-}
+    if (tdzRequirement == TDZRequirement::UnderTDZ)
+        m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks));
 
-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
-{
-    VariableEnvironment& environment = node->lexicalVariables();
-    pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult);
+    if (tdzRequirement == TDZRequirement::UnderTDZ) {
+        // Prefill stack variables with the TDZ empty value.
+        // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
+        for (auto& entry : environment) {
+            SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get());
+            ASSERT(!symbolTableEntry.isNull());
+            VarOffset offset = symbolTableEntry.varOffset();
+            if (offset.isScope()) {
+                ASSERT(newScope);
+                continue;
+            }
+            ASSERT(offset.isStack());
+            emitMoveEmptyValue(&registerFor(offset.stackOffset()));
+        }
+    }
 }
 
 void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node)
 {
     VariableEnvironment& environment = node->lexicalVariables();
+    popLexicalScopeInternal(environment, TDZRequirement::UnderTDZ);
+}
+
+void BytecodeGenerator::popLexicalScopeInternal(VariableEnvironment& environment, TDZRequirement tdzRequirement)
+{
     if (!environment.size())
         return;
 
@@ -1451,7 +1468,7 @@
     Strong<SymbolTable> symbolTable = stackEntry.m_symbolTable;
     ConcurrentJITLocker locker(symbolTable->m_lock);
     bool hasCapturedVariables = false;
-    for (auto entry : environment) {
+    for (auto& entry : environment) {
         if (entry.value.isCaptured()) {
             hasCapturedVariables = true;
             continue;
@@ -1471,7 +1488,8 @@
         stackEntry.m_scope->deref();
     }
 
-    m_TDZStack.removeLast();
+    if (tdzRequirement == TDZRequirement::UnderTDZ)
+        m_TDZStack.removeLast();
 }
 
 void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode* node, RegisterID* loopSymbolTable)
@@ -1576,14 +1594,14 @@
     // }
     for (unsigned i = m_symbolTableStack.size(); i--; ) {
         SymbolTableStackEntry& stackEntry = m_symbolTableStack[i];
-        if (stackEntry.m_isWithOrCatch)
+        if (stackEntry.m_isWithScope)
             return Variable(property);
         Strong<SymbolTable>& symbolTable = stackEntry.m_symbolTable;
         SymbolTableEntry symbolTableEntry = symbolTable->get(property.impl());
         if (symbolTableEntry.isNull())
             continue;
         
-        return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->correspondsToLexicalScope());
+        return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope);
     }
 
     return Variable(property);
@@ -1661,7 +1679,7 @@
 ResolveType BytecodeGenerator::resolveType()
 {
     for (unsigned i = m_symbolTableStack.size(); i--; ) {
-        if (m_symbolTableStack[i].m_isWithOrCatch)
+        if (m_symbolTableStack[i].m_isWithScope)
             return Dynamic;
     }
 
@@ -1688,9 +1706,9 @@
         // that code sensible and obviate the need for us to do bad things.
         for (unsigned i = m_symbolTableStack.size(); i--; ) {
             SymbolTableStackEntry& stackEntry = m_symbolTableStack[i];
-            // We should not resolve a variable to VarKind::Scope if a "with" or "catch" scope lies in between the current
+            // We should not resolve a variable to VarKind::Scope if a "with" scope lies in between the current
             // scope and the resolved scope.
-            RELEASE_ASSERT(!stackEntry.m_isWithOrCatch);
+            RELEASE_ASSERT(!stackEntry.m_isWithScope);
 
             if (stackEntry.m_symbolTable->get(variable.ident().impl()).isNull())
                 continue;
@@ -2567,12 +2585,12 @@
     emitMove(dst, parentScope.get());
 }
 
-void BytecodeGenerator::emitPopWithOrCatchScope(RegisterID* srcDst)
+void BytecodeGenerator::emitPopWithScope(RegisterID* srcDst)
 {
     emitPopScope(srcDst, srcDst);
     popScopedControlFlowContext();
     SymbolTableStackEntry stackEntry = m_symbolTableStack.takeLast();
-    RELEASE_ASSERT(stackEntry.m_isWithOrCatch);
+    RELEASE_ASSERT(stackEntry.m_isWithScope);
 }
 
 void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, unsigned line, unsigned charOffset, unsigned lineStart)
@@ -3007,17 +3025,19 @@
     m_localScopeDepth--;
 }
 
-void BytecodeGenerator::emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
+void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment& environment)
 {
-    pushScopedControlFlowContext();
+    RELEASE_ASSERT(environment.contains(property.impl()));
+    pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope);
+    Variable exceptionVar = variable(property);
+    RELEASE_ASSERT(exceptionVar.isResolved());
+    RefPtr<RegisterID> scope = emitResolveScope(nullptr, exceptionVar);
+    emitPutToScope(scope.get(), exceptionVar, exceptionValue, ThrowIfNotFound);
+}
 
-    emitOpcode(op_push_name_scope);
-    instructions().append(dst->index());
-    instructions().append(value->index());
-    instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index());
-    instructions().append(JSNameScope::CatchScope);
-
-    m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(), nullptr, true, 0 });
+void BytecodeGenerator::emitPopCatchScope(VariableEnvironment& environment) 
+{
+    popLexicalScopeInternal(environment, TDZRequirement::NotUnderTDZ);
 }
 
 void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 3adc510..347f0fe 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -581,12 +581,13 @@
         void emitThrowTypeError(const String& message);
 
         void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
-        void emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
+        void emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment&);
+        void emitPopCatchScope(VariableEnvironment&);
 
         void emitGetScope();
         RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope);
         void emitPopScope(RegisterID* dst, RegisterID* scope);
-        void emitPopWithOrCatchScope(RegisterID* srcDst);
+        void emitPopWithScope(RegisterID* srcDst);
         RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
 
         void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
@@ -622,7 +623,10 @@
         OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
 
     private:
-        void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult);
+        enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
+        enum class ScopeType { CatchScope, LetConstScope };
+        void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType);
+        void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
     public:
         void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
         void popLexicalScope(VariableEnvironmentNode*);
@@ -738,7 +742,7 @@
         struct SymbolTableStackEntry {
             Strong<SymbolTable> m_symbolTable;
             RegisterID* m_scope;
-            bool m_isWithOrCatch;
+            bool m_isWithScope;
             int m_symbolTableConstantIndex;
         };
         Vector<SymbolTableStackEntry> m_symbolTableStack;
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index da46b9f..7c4ea62 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -1858,8 +1858,8 @@
             generator.emitTDZCheckIfNecessary(var, local, nullptr);
 
         if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) {
+            result = generator.emitNode(dst, m_right); // Execute side effects first.
             generator.emitReadOnlyExceptionIfNeeded(var);
-            result = generator.emitNode(dst, m_right);
         } else if (var.isSpecial() || generator.vm()->typeProfiler()) {
             RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
             generator.emitNode(tempDst.get(), m_right);
@@ -1888,9 +1888,10 @@
         dst = 0;
     RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
     if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) {
+        RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
         bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
         if (threwException)
-            return generator.emitNode(dst, m_right);
+            return result;
     }
     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
@@ -2683,7 +2684,7 @@
     generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
     generator.emitPushWithScope(generator.scopeRegister(), scope.get());
     generator.emitNode(dst, m_statement);
-    generator.emitPopWithOrCatchScope(generator.scopeRegister());
+    generator.emitPopWithScope(generator.scopeRegister());
 }
 
 // ------------------------------ CaseClauseNode --------------------------------
@@ -2933,10 +2934,10 @@
             tryData = generator.pushTry(here.get());
         }
 
-        generator.emitPushCatchScope(generator.scopeRegister(), m_thrownValueIdent, thrownValueRegister.get(), DontDelete);
+        generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_catchEnvironment);
         generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
         generator.emitNode(dst, m_catchBlock);
-        generator.emitPopWithOrCatchScope(generator.scopeRegister());
+        generator.emitPopCatchScope(m_catchEnvironment);
         generator.emitLabel(catchEndLabel.get());
     }
 
diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.cpp b/Source/JavaScriptCore/debugger/DebuggerScope.cpp
index 6373223..e4788da 100644
--- a/Source/JavaScriptCore/debugger/DebuggerScope.cpp
+++ b/Source/JavaScriptCore/debugger/DebuggerScope.cpp
@@ -167,7 +167,7 @@
 
 bool DebuggerScope::isCatchScope() const
 {
-    return m_scope->isCatchScopeObject();
+    return m_scope->isCatchScope();
 }
 
 bool DebuggerScope::isFunctionNameScope() const
@@ -190,13 +190,20 @@
     // In the current debugger implementation, every function or eval will create an
     // lexical environment object. Hence, a lexical environment object implies a
     // function or eval scope.
-    return m_scope->isActivationObject();
+    return m_scope->isActivationObject() && !isCatchScope();
 }
 
-JSValue DebuggerScope::caughtValue() const
+JSValue DebuggerScope::caughtValue(ExecState* exec) const
 {
     ASSERT(isCatchScope());
-    return reinterpret_cast<JSNameScope*>(m_scope.get())->value();
+    JSLexicalEnvironment* catchEnvironment = jsCast<JSLexicalEnvironment*>(m_scope.get());
+    SymbolTable* catchSymbolTable = catchEnvironment->symbolTable();
+    RELEASE_ASSERT(catchSymbolTable->size() == 1);
+    PropertyName errorName(catchSymbolTable->begin(catchSymbolTable->m_lock)->key.get());
+    PropertySlot slot(m_scope.get());
+    bool success = catchEnvironment->getOwnPropertySlot(catchEnvironment, exec, errorName, slot);
+    RELEASE_ASSERT(success && slot.isValue());
+    return slot.getValue(exec, errorName);
 }
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.h b/Source/JavaScriptCore/debugger/DebuggerScope.h
index 4416684..e1edb92 100644
--- a/Source/JavaScriptCore/debugger/DebuggerScope.h
+++ b/Source/JavaScriptCore/debugger/DebuggerScope.h
@@ -91,7 +91,7 @@
     bool isGlobalScope() const;
     bool isFunctionOrEvalScope() const;
 
-    JSValue caughtValue() const;
+    JSValue caughtValue(ExecState*) const;
 
 private:
     JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
diff --git a/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp b/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
index 74602c5..356de1c 100644
--- a/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
+++ b/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
@@ -340,7 +340,7 @@
     while (debuggerCallFrame) {
         DebuggerScope* scope = debuggerCallFrame->scope();
         if (scope->isCatchScope())
-            return Deprecated::ScriptValue(state->vm(), scope->caughtValue());
+            return Deprecated::ScriptValue(state->vm(), scope->caughtValue(state));
         debuggerCallFrame = debuggerCallFrame->callerFrame();
     }
 
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index bf94b90..a25f583 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -1140,7 +1140,7 @@
                 break;
             } 
             if (JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(node)) {
-                if (!lexicalEnvironment->symbolTable()->correspondsToLexicalScope()) {
+                if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
                     variableObject = node;
                     break;
                 }
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index c85871b..54db327 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -497,11 +497,6 @@
 {
     int dst = currentInstruction[1].u.operand;
     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
-    if (currentInstruction[4].u.operand == JSNameScope::CatchScope) {
-        callOperation(operationPushCatchScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT0);
-        return;
-    }
-
     RELEASE_ASSERT(currentInstruction[4].u.operand == JSNameScope::FunctionNameScope);
     callOperation(operationPushFunctionNameScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT0);
 }
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 932657f..2863508 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -804,11 +804,6 @@
 {
     int dst = currentInstruction[1].u.operand;
     emitLoad(currentInstruction[2].u.operand, regT1, regT0);
-    if (currentInstruction[4].u.operand == JSNameScope::CatchScope) {
-        callOperation(operationPushCatchScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT1, regT0);
-        return;
-    }
-
     RELEASE_ASSERT(currentInstruction[4].u.operand == JSNameScope::FunctionNameScope);
     callOperation(operationPushFunctionNameScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT1, regT0);
 }
diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp
index a01f2a8..4b58b44 100644
--- a/Source/JavaScriptCore/jit/JITOperations.cpp
+++ b/Source/JavaScriptCore/jit/JITOperations.cpp
@@ -44,7 +44,6 @@
 #include "JIT.h"
 #include "JITToDFGDeferredCompilationCallback.h"
 #include "JSCInlines.h"
-#include "JSCatchScope.h"
 #include "JSFunctionNameScope.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSLexicalEnvironment.h"
@@ -1364,11 +1363,6 @@
 }
 #endif
 
-void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
-{
-    pushNameScope<JSCatchScope>(exec, dst, symbolTable, encodedValue);
-}
-
 void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
 {
     pushNameScope<JSFunctionNameScope>(exec, dst, symbolTable, encodedValue);
diff --git a/Source/JavaScriptCore/jit/JITOperations.h b/Source/JavaScriptCore/jit/JITOperations.h
index 299184b..1709d25 100644
--- a/Source/JavaScriptCore/jit/JITOperations.h
+++ b/Source/JavaScriptCore/jit/JITOperations.h
@@ -304,7 +304,6 @@
 void JIT_OPERATION operationPutSetterById(ExecState*, JSCell*, Identifier*, JSCell*) WTF_INTERNAL;
 void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, Identifier*, JSCell*, JSCell*) WTF_INTERNAL;
 #endif
-void JIT_OPERATION operationPushCatchScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;
 void JIT_OPERATION operationPushFunctionNameScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;
 void JIT_OPERATION operationPushWithScope(ExecState*, int32_t, EncodedJSValue) WTF_INTERNAL;
 void JIT_OPERATION operationPopScope(ExecState*, int32_t) WTF_INTERNAL;
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h
index c28c62e..36216d4 100644
--- a/Source/JavaScriptCore/parser/ASTBuilder.h
+++ b/Source/JavaScriptCore/parser/ASTBuilder.h
@@ -555,9 +555,9 @@
         return result;
     }
 
-    StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
+    StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine, VariableEnvironment& catchEnvironment)
     {
-        TryNode* result = new (m_parserArena) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock);
+        TryNode* result = new (m_parserArena) TryNode(location, tryBlock, *ident, catchBlock, catchEnvironment, finallyBlock);
         if (catchBlock)
             usesCatch();
         result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h
index 6cd7627..dd20b8f 100644
--- a/Source/JavaScriptCore/parser/NodeConstructors.h
+++ b/Source/JavaScriptCore/parser/NodeConstructors.h
@@ -818,13 +818,14 @@
     {
     }
 
-    inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& thrownValueIdent, StatementNode* catchBlock, StatementNode* finallyBlock)
+    inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& thrownValueIdent, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock)
         : StatementNode(location)
         , m_tryBlock(tryBlock)
         , m_thrownValueIdent(thrownValueIdent)
         , m_catchBlock(catchBlock)
         , m_finallyBlock(finallyBlock)
     {
+        m_catchEnvironment.swap(catchEnvironment);
     }
 
     inline FunctionParameters::FunctionParameters()
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h
index 92fa7e6..000d860 100644
--- a/Source/JavaScriptCore/parser/Nodes.h
+++ b/Source/JavaScriptCore/parser/Nodes.h
@@ -1513,7 +1513,7 @@
 
     class TryNode : public StatementNode {
     public:
-        TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);
+        TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock);
 
     private:
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
@@ -1522,6 +1522,7 @@
         const Identifier& m_thrownValueIdent;
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
+        VariableEnvironment m_catchEnvironment;
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRoot, public VariableEnvironmentNode {
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index e00a73a..289f38e 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -1261,9 +1261,8 @@
     tryBlock = parseBlockStatement(context);
     failIfFalse(tryBlock, "Cannot parse the body of try block");
     int lastLine = m_lastTokenEndPosition.line;
-    
+    VariableEnvironment catchEnvironment; 
     if (match(CATCH)) {
-        currentScope()->setNeedsFullActivation();
         next();
         
         handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
@@ -1274,12 +1273,15 @@
         ident = m_token.m_data.ident;
         next();
         AutoPopScopeRef catchScope(this, pushScope());
-        failIfTrueIfStrict(declareVariable(ident) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
-        catchScope->preventAllVariableDeclarations();
+        catchScope->setIsLexicalScope();
+        catchScope->preventVarDeclarations();
+        failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
         handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
         matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
         catchBlock = parseBlockStatement(context);
         failIfFalse(catchBlock, "Unable to parse 'catch' block");
+        catchEnvironment = catchScope->finalizeLexicalEnvironment();
+        RELEASE_ASSERT(catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl()));
         popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
     }
     
@@ -1290,7 +1292,7 @@
         failIfFalse(finallyBlock, "Cannot parse finally body");
     }
     failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
-    return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
+    return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
 }
 
 template <typename LexerType>
diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h
index 23f448f..786ca8c 100644
--- a/Source/JavaScriptCore/parser/SyntaxChecker.h
+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h
@@ -242,7 +242,7 @@
     int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
     int createContinueStatement(const JSTokenLocation&, int, int) { return StatementResult; }
     int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
-    int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int) { return StatementResult; }
+    int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int, VariableEnvironment&) { return StatementResult; }
     int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
     int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
     int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int) { return StatementResult; }
diff --git a/Source/JavaScriptCore/runtime/JSCatchScope.cpp b/Source/JavaScriptCore/runtime/JSCatchScope.cpp
deleted file mode 100644
index 15e49dd..0000000
--- a/Source/JavaScriptCore/runtime/JSCatchScope.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "JSCatchScope.h"
-
-#include "JSCInlines.h"
-
-namespace JSC {
-
-const ClassInfo JSCatchScope::s_info = { "CatchScope", &Base::s_info, 0, CREATE_METHOD_TABLE(JSCatchScope) };
-
-} // namespace JSC
-
diff --git a/Source/JavaScriptCore/runtime/JSCatchScope.h b/Source/JavaScriptCore/runtime/JSCatchScope.h
deleted file mode 100644
index 0eeab90..0000000
--- a/Source/JavaScriptCore/runtime/JSCatchScope.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef JSCatchScope_h
-#define JSCatchScope_h
-
-#include "JSNameScope.h"
-
-namespace JSC {
-
-class JSCatchScope : public JSNameScope {
-public:
-    typedef JSNameScope Base;
-
-private:
-    friend class JSNameScope;
-    
-    JSCatchScope(VM& vm, JSGlobalObject* globalObject, JSScope* next, SymbolTable* symbolTable)
-        : Base(vm, globalObject->catchScopeStructure(), next, symbolTable)
-    {
-    }
-    
-public:
-    static JSCatchScope* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value)
-    {
-        return Base::create<JSCatchScope>(vm, globalObject, currentScope, symbolTable, value);
-    }
-    
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
-    {
-        return Structure::create(vm, globalObject, proto, TypeInfo(NameScopeObjectType, StructureFlags), info());
-    }
-    
-    DECLARE_INFO;
-};
-
-} // namespace JSC
-
-#endif // JSCatchScope_h
-
diff --git a/Source/JavaScriptCore/runtime/JSFunctionNameScope.h b/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
index 922e89a..7de66ee 100644
--- a/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
+++ b/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
@@ -38,7 +38,7 @@
     friend class JSNameScope;
     
     JSFunctionNameScope(VM& vm, JSGlobalObject* globalObject, JSScope* next, SymbolTable* symbolTable)
-        : Base(vm, globalObject->catchScopeStructure(), next, symbolTable)
+        : Base(vm, globalObject->functionNameScopeStructure(), next, symbolTable)
     {
     }
     
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 26183ef..29f1037 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -64,7 +64,6 @@
 #include "JSCallbackConstructor.h"
 #include "JSCallbackFunction.h"
 #include "JSCallbackObject.h"
-#include "JSCatchScope.h"
 #include "JSConsole.h"
 #include "JSDataView.h"
 #include "JSDataViewPrototype.h"
@@ -302,7 +301,6 @@
     m_typedArrays[toIndex(TypeFloat64)].structure.set(vm, this, JSFloat64Array::createStructure(vm, this, m_typedArrays[toIndex(TypeFloat64)].prototype.get()));
     m_typedArrays[toIndex(TypeDataView)].structure.set(vm, this, JSDataView::createStructure(vm, this, m_typedArrays[toIndex(TypeDataView)].prototype.get()));
     
-    m_catchScopeStructure.set(vm, this, JSCatchScope::createStructure(vm, this, jsNull()));
     m_functionNameScopeStructure.set(vm, this, JSFunctionNameScope::createStructure(vm, this, jsNull()));
     m_lexicalEnvironmentStructure.set(vm, this, JSLexicalEnvironment::createStructure(vm, this));
     m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
@@ -773,7 +771,6 @@
     visitor.append(&thisObject->m_withScopeStructure);
     visitor.append(&thisObject->m_strictEvalActivationStructure);
     visitor.append(&thisObject->m_lexicalEnvironmentStructure);
-    visitor.append(&thisObject->m_catchScopeStructure);
     visitor.append(&thisObject->m_functionNameScopeStructure);
     visitor.append(&thisObject->m_directArgumentsStructure);
     visitor.append(&thisObject->m_scopedArgumentsStructure);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 99879d1..5792ac2 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -211,7 +211,6 @@
     WriteBarrier<Structure> m_withScopeStructure;
     WriteBarrier<Structure> m_strictEvalActivationStructure;
     WriteBarrier<Structure> m_lexicalEnvironmentStructure;
-    WriteBarrier<Structure> m_catchScopeStructure;
     WriteBarrier<Structure> m_functionNameScopeStructure;
     WriteBarrier<Structure> m_directArgumentsStructure;
     WriteBarrier<Structure> m_scopedArgumentsStructure;
@@ -423,7 +422,6 @@
     Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
     Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
     Structure* activationStructure() const { return m_lexicalEnvironmentStructure.get(); }
-    Structure* catchScopeStructure() const { return m_catchScopeStructure.get(); }
     Structure* functionNameScopeStructure() const { return m_functionNameScopeStructure.get(); }
     Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); }
     Structure* scopedArgumentsStructure() const { return m_scopedArgumentsStructure.get(); }
diff --git a/Source/JavaScriptCore/runtime/JSNameScope.cpp b/Source/JavaScriptCore/runtime/JSNameScope.cpp
index d159f69..3d4a371 100644
--- a/Source/JavaScriptCore/runtime/JSNameScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSNameScope.cpp
@@ -28,7 +28,6 @@
 
 #include "Error.h"
 #include "JSCInlines.h"
-#include "JSCatchScope.h"
 #include "JSFunctionNameScope.h"
 
 namespace JSC {
@@ -37,14 +36,8 @@
 
 JSNameScope* JSNameScope::create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value, Type type)
 {
-    switch (type) {
-    case CatchScope:
-        return JSCatchScope::create(vm, globalObject, currentScope, symbolTable, value);
-    case FunctionNameScope:
-        return JSFunctionNameScope::create(vm, globalObject, currentScope, symbolTable, value);
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return nullptr;
+    RELEASE_ASSERT(type == FunctionNameScope);
+    return JSFunctionNameScope::create(vm, globalObject, currentScope, symbolTable, value);
 }
 
 JSValue JSNameScope::toThis(JSCell*, ExecState* exec, ECMAMode ecmaMode)
diff --git a/Source/JavaScriptCore/runtime/JSNameScope.h b/Source/JavaScriptCore/runtime/JSNameScope.h
index db8d008..54a77b8 100644
--- a/Source/JavaScriptCore/runtime/JSNameScope.h
+++ b/Source/JavaScriptCore/runtime/JSNameScope.h
@@ -38,7 +38,6 @@
     static const unsigned StructureFlags = Base::StructureFlags| OverridesGetOwnPropertySlot;
 
     enum Type {
-        CatchScope,
         FunctionNameScope
     };
 
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 9d49849..01500a6 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -35,7 +35,6 @@
 #include "Executable.h"
 #include "GetterSetter.h"
 #include "IndexingHeaderInlines.h"
-#include "JSCatchScope.h"
 #include "JSFunction.h"
 #include "JSFunctionNameScope.h"
 #include "JSGlobalObject.h"
@@ -1602,11 +1601,6 @@
     return jsCast<JSObject*>(cell);
 }
 
-bool JSObject::isCatchScopeObject() const
-{
-    return inherits(JSCatchScope::info());
-}
-
 bool JSObject::isFunctionNameScopeObject() const
 {
     return inherits(JSFunctionNameScope::info());
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index d5c61ba..5e1b35a 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -601,7 +601,6 @@
     bool isVariableObject() const;
     bool isStaticScopeObject() const;
     bool isNameScopeObject() const;
-    bool isCatchScopeObject() const;
     bool isFunctionNameScopeObject() const;
     bool isActivationObject() const;
     bool isErrorInstance() const;
diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp
index 5022b5d..9ef9df0 100644
--- a/Source/JavaScriptCore/runtime/JSScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSScope.cpp
@@ -193,7 +193,7 @@
         if (!scope->isLexicalScope())
             continue;
         SymbolTable* symbolTable = jsCast<JSLexicalEnvironment*>(scope)->symbolTable();
-        ASSERT(symbolTable->correspondsToLexicalScope());
+        ASSERT(symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope);
         ConcurrentJITLocker locker(symbolTable->m_lock);
         for (auto end = symbolTable->end(locker), iter = symbolTable->begin(locker); iter != end; ++iter)
             result.add(iter->key);
@@ -206,9 +206,18 @@
     if (!lexicalEnvironment) // Global object does not hold any lexical variables so we can ignore it.
         return false;
 
-    return lexicalEnvironment->symbolTable()->correspondsToLexicalScope();
+    return lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::LexicalScope;
 }
 
+bool JSScope::isCatchScope()
+{
+    JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(this);
+    if (!lexicalEnvironment)
+        return false;
+    return lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::CatchScope;
+}
+
+
 const char* resolveModeName(ResolveMode mode)
 {
     static const char* const names[] = {
diff --git a/Source/JavaScriptCore/runtime/JSScope.h b/Source/JavaScriptCore/runtime/JSScope.h
index feb8832..5117f2a 100644
--- a/Source/JavaScriptCore/runtime/JSScope.h
+++ b/Source/JavaScriptCore/runtime/JSScope.h
@@ -165,6 +165,7 @@
     static void visitChildren(JSCell*, SlotVisitor&);
 
     bool isLexicalScope();
+    bool isCatchScope();
 
     ScopeChainIterator begin();
     ScopeChainIterator end();
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp
index e62599f..02f943f 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.cpp
+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp
@@ -84,7 +84,7 @@
 SymbolTable::SymbolTable(VM& vm)
     : JSCell(vm, vm.symbolTableStructure.get())
     , m_usesNonStrictEval(false)
-    , m_correspondsToLexicalScope(false)
+    , m_scopeType(VarScope)
 {
 }
 
@@ -142,7 +142,7 @@
     SymbolTable* result = SymbolTable::create(vm);
     
     result->m_usesNonStrictEval = m_usesNonStrictEval;
-    result->m_correspondsToLexicalScope = m_correspondsToLexicalScope;
+    result->m_scopeType = m_scopeType;
 
     for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
         if (!iter->value.varOffset().isScope())
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index fa2cf93..6849150 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -648,8 +648,14 @@
 
     bool usesNonStrictEval() { return m_usesNonStrictEval; }
     void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
-    ALWAYS_INLINE bool correspondsToLexicalScope() { return m_correspondsToLexicalScope; }
-    void setDoesCorrespondToLexicalScope() { m_correspondsToLexicalScope = true; }
+
+    enum ScopeType {
+        VarScope,
+        LexicalScope,
+        CatchScope
+    };
+    void setScopeType(ScopeType type) { m_scopeType = type; }
+    ScopeType scopeType() const { return static_cast<ScopeType>(m_scopeType); }
 
     SymbolTable* cloneScopePart(VM&);
 
@@ -678,7 +684,7 @@
     std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData;
 
     bool m_usesNonStrictEval : 1;
-    bool m_correspondsToLexicalScope : 1;
+    unsigned m_scopeType : 2; // ScopeType
     
     WriteBarrier<ScopedArgumentsTable> m_arguments;
     WriteBarrier<InferredValue> m_singletonScope;
diff --git a/Source/JavaScriptCore/tests/stress/const-semantics.js b/Source/JavaScriptCore/tests/stress/const-semantics.js
index b7079a9..d24e066 100644
--- a/Source/JavaScriptCore/tests/stress/const-semantics.js
+++ b/Source/JavaScriptCore/tests/stress/const-semantics.js
@@ -188,17 +188,29 @@
     function taz() {
         const x = 20;
         shouldThrowInvalidConstAssignment(function() { x = 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x += 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x -= 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x *= 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x /= 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x >>= 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x <<= 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x ^= 20; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x++; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { x--; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { ++x; });
+        assert(x === 20);
         shouldThrowInvalidConstAssignment(function() { --x; });
+        assert(x === 20);
     }
     function jaz() {
         const x = 20;