Title: [208712] trunk/Source/_javascript_Core
Revision
208712
Author
[email protected]
Date
2016-11-14 14:57:12 -0800 (Mon, 14 Nov 2016)

Log Message

JSC should distinguish between local and global eval
https://bugs.webkit.org/show_bug.cgi?id=164628

Reviewed by Saam Barati.

Local use of the 'eval' keyword and invocation of the global window.eval
function are distinct operations in _javascript_.

This patch splits out LocalEvalExecutable vs GlobalEvalExecutable in
order to help distinguish these operations in code.

Our code used to do some silly things for lack of distinguishing these
cases. For example, it would double cache local eval in CodeCache and
EvalCodeCache. This made CodeCache seem more complicated than it really
was.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj: Added some files.

* bytecode/CodeBlock.h:

* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::tryGet):
(JSC::EvalCodeCache::set):
(JSC::EvalCodeCache::getSlow): Deleted. Moved code generation out of
the cache to avoid tight coupling. Now the cache just caches.

* bytecode/UnlinkedEvalCodeBlock.h:
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::fromGlobalCode):
* bytecode/UnlinkedModuleProgramCodeBlock.h:
* bytecode/UnlinkedProgramCodeBlock.h:
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::evaluateWithScopeExtension): Updated for interface
changes.

* interpreter/Interpreter.cpp:
(JSC::eval): Moved code generation here so the cache didn't need to build
it in.

* llint/LLIntOffsetsExtractor.cpp:

* runtime/CodeCache.cpp:
(JSC::CodeCache::getUnlinkedGlobalCodeBlock): No need to check for TDZ
variables any more. We only cache global programs, and global variable
access always does TDZ checks.

(JSC::CodeCache::getUnlinkedProgramCodeBlock):
(JSC::CodeCache::getUnlinkedGlobalEvalCodeBlock):
(JSC::CodeCache::getUnlinkedModuleProgramCodeBlock):
(JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):

(JSC::CodeCache::CodeCache): Deleted.
(JSC::CodeCache::~CodeCache): Deleted.
(JSC::CodeCache::getGlobalCodeBlock): Deleted.
(JSC::CodeCache::getProgramCodeBlock): Deleted.
(JSC::CodeCache::getEvalCodeBlock): Deleted.
(JSC::CodeCache::getModuleProgramCodeBlock): Deleted.
(JSC::CodeCache::getFunctionExecutableFromGlobalCode): Deleted.

* runtime/CodeCache.h:
(JSC::CodeCache::clear):
(JSC::generateUnlinkedCodeBlock): Moved unlinked code block creation
out of the CodeCache class and into a stand-alone function because
we need it for local eval, which does not live in CodeCache.

* runtime/EvalExecutable.cpp:
(JSC::EvalExecutable::create): Deleted.
* runtime/EvalExecutable.h:
(): Deleted.
* runtime/GlobalEvalExecutable.cpp: Added.
(JSC::GlobalEvalExecutable::create):
(JSC::GlobalEvalExecutable::GlobalEvalExecutable):
* runtime/GlobalEvalExecutable.h: Added.
* runtime/LocalEvalExecutable.cpp: Added.
(JSC::LocalEvalExecutable::create):
(JSC::LocalEvalExecutable::LocalEvalExecutable):
* runtime/LocalEvalExecutable.h: Added. Split out Local vs Global
EvalExecutable classes to distinguish these operations in code. The key
difference is that LocalEvalExecutable does not live in the CodeCache
and only lives in the EvalCodeCache.

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::createProgramCodeBlock):
(JSC::JSGlobalObject::createLocalEvalCodeBlock):
(JSC::JSGlobalObject::createGlobalEvalCodeBlock):
(JSC::JSGlobalObject::createModuleProgramCodeBlock):
(JSC::JSGlobalObject::createEvalCodeBlock): Deleted.
* runtime/JSGlobalObject.h:
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):

* runtime/JSScope.cpp:
(JSC::JSScope::collectClosureVariablesUnderTDZ):
(JSC::JSScope::collectVariablesUnderTDZ): Deleted. We don't include
global lexical variables in our concept of TDZ scopes anymore. Global
variable access always does TDZ checks unconditionally. So, only closure
scope accesses give specific consideration to TDZ checks.

* runtime/JSScope.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (208711 => 208712)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2016-11-14 22:57:12 UTC (rev 208712)
@@ -683,6 +683,7 @@
     runtime/DatePrototype.cpp
     runtime/DirectArguments.cpp
     runtime/DirectArgumentsOffset.cpp
+    runtime/DirectEvalExecutable.cpp
     runtime/DumpContext.cpp
     runtime/ECMAScriptSpecInternalFunctions.cpp
     runtime/Error.cpp
@@ -710,6 +711,7 @@
     runtime/HashMapImpl.cpp
     runtime/Identifier.cpp
     runtime/IndexingType.cpp
+    runtime/IndirectEvalExecutable.cpp
     runtime/InferredType.cpp
     runtime/InferredTypeTable.cpp
     runtime/InferredValue.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (208711 => 208712)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-14 22:57:12 UTC (rev 208712)
@@ -1,3 +1,106 @@
+2016-11-11  Geoffrey Garen  <[email protected]>
+
+        JSC should distinguish between local and global eval
+        https://bugs.webkit.org/show_bug.cgi?id=164628
+
+        Reviewed by Saam Barati.
+
+        Local use of the 'eval' keyword and invocation of the global window.eval
+        function are distinct operations in _javascript_.
+
+        This patch splits out LocalEvalExecutable vs GlobalEvalExecutable in
+        order to help distinguish these operations in code.
+
+        Our code used to do some silly things for lack of distinguishing these
+        cases. For example, it would double cache local eval in CodeCache and
+        EvalCodeCache. This made CodeCache seem more complicated than it really
+        was.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj: Added some files.
+
+        * bytecode/CodeBlock.h:
+
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::tryGet):
+        (JSC::EvalCodeCache::set):
+        (JSC::EvalCodeCache::getSlow): Deleted. Moved code generation out of
+        the cache to avoid tight coupling. Now the cache just caches.
+
+        * bytecode/UnlinkedEvalCodeBlock.h:
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::fromGlobalCode):
+        * bytecode/UnlinkedModuleProgramCodeBlock.h:
+        * bytecode/UnlinkedProgramCodeBlock.h:
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::evaluateWithScopeExtension): Updated for interface
+        changes.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::eval): Moved code generation here so the cache didn't need to build
+        it in.
+
+        * llint/LLIntOffsetsExtractor.cpp:
+
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getUnlinkedGlobalCodeBlock): No need to check for TDZ
+        variables any more. We only cache global programs, and global variable
+        access always does TDZ checks.
+
+        (JSC::CodeCache::getUnlinkedProgramCodeBlock):
+        (JSC::CodeCache::getUnlinkedGlobalEvalCodeBlock):
+        (JSC::CodeCache::getUnlinkedModuleProgramCodeBlock):
+        (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
+
+        (JSC::CodeCache::CodeCache): Deleted.
+        (JSC::CodeCache::~CodeCache): Deleted.
+        (JSC::CodeCache::getGlobalCodeBlock): Deleted.
+        (JSC::CodeCache::getProgramCodeBlock): Deleted.
+        (JSC::CodeCache::getEvalCodeBlock): Deleted.
+        (JSC::CodeCache::getModuleProgramCodeBlock): Deleted.
+        (JSC::CodeCache::getFunctionExecutableFromGlobalCode): Deleted.
+
+        * runtime/CodeCache.h:
+        (JSC::CodeCache::clear):
+        (JSC::generateUnlinkedCodeBlock): Moved unlinked code block creation
+        out of the CodeCache class and into a stand-alone function because
+        we need it for local eval, which does not live in CodeCache.
+
+        * runtime/EvalExecutable.cpp:
+        (JSC::EvalExecutable::create): Deleted.
+        * runtime/EvalExecutable.h:
+        (): Deleted.
+        * runtime/GlobalEvalExecutable.cpp: Added.
+        (JSC::GlobalEvalExecutable::create):
+        (JSC::GlobalEvalExecutable::GlobalEvalExecutable):
+        * runtime/GlobalEvalExecutable.h: Added.
+        * runtime/LocalEvalExecutable.cpp: Added.
+        (JSC::LocalEvalExecutable::create):
+        (JSC::LocalEvalExecutable::LocalEvalExecutable):
+        * runtime/LocalEvalExecutable.h: Added. Split out Local vs Global
+        EvalExecutable classes to distinguish these operations in code. The key
+        difference is that LocalEvalExecutable does not live in the CodeCache
+        and only lives in the EvalCodeCache.
+
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::createProgramCodeBlock):
+        (JSC::JSGlobalObject::createLocalEvalCodeBlock):
+        (JSC::JSGlobalObject::createGlobalEvalCodeBlock):
+        (JSC::JSGlobalObject::createModuleProgramCodeBlock):
+        (JSC::JSGlobalObject::createEvalCodeBlock): Deleted.
+        * runtime/JSGlobalObject.h:
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncEval):
+
+        * runtime/JSScope.cpp:
+        (JSC::JSScope::collectClosureVariablesUnderTDZ):
+        (JSC::JSScope::collectVariablesUnderTDZ): Deleted. We don't include
+        global lexical variables in our concept of TDZ scopes anymore. Global
+        variable access always does TDZ checks unconditionally. So, only closure
+        scope accesses give specific consideration to TDZ checks.
+
+        * runtime/JSScope.h:
+
 2016-11-14  Caitlin Potter  <[email protected]>
 
         [JSC] Handle new_async_func / new_async_func_exp in DFG / FTL

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (208711 => 208712)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-11-14 22:57:12 UTC (rev 208712)
@@ -1055,6 +1055,10 @@
 		142E313A134FF0A600AFADB5 /* LocalScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3131134FF0A600AFADB5 /* LocalScope.h */; };
 		142E313B134FF0A600AFADB5 /* Strong.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3132134FF0A600AFADB5 /* Strong.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		142E313C134FF0A600AFADB5 /* Weak.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3133134FF0A600AFADB5 /* Weak.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		14386A741DD69895008652C4 /* DirectEvalExecutable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14386A721DD69895008652C4 /* DirectEvalExecutable.cpp */; };
+		14386A751DD69895008652C4 /* DirectEvalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14386A731DD69895008652C4 /* DirectEvalExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		14386A781DD6989C008652C4 /* IndirectEvalExecutable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */; };
+		14386A791DD6989C008652C4 /* IndirectEvalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1440057F0A5335640005F061 /* JSNode.c in Sources */ = {isa = PBXBuildFile; fileRef = 1440F6420A4F8B6A0005F061 /* JSNode.c */; };
 		144005CB0A5338D10005F061 /* JSNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 1440F6410A4F8B6A0005F061 /* JSNode.h */; };
 		144005CC0A5338F80005F061 /* Node.h in Headers */ = {isa = PBXBuildFile; fileRef = 1440051F0A531D3B0005F061 /* Node.h */; };
@@ -3433,6 +3437,10 @@
 		142E3131134FF0A600AFADB5 /* LocalScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalScope.h; sourceTree = "<group>"; };
 		142E3132134FF0A600AFADB5 /* Strong.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Strong.h; sourceTree = "<group>"; };
 		142E3133134FF0A600AFADB5 /* Weak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Weak.h; sourceTree = "<group>"; };
+		14386A721DD69895008652C4 /* DirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectEvalExecutable.cpp; sourceTree = "<group>"; };
+		14386A731DD69895008652C4 /* DirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectEvalExecutable.h; sourceTree = "<group>"; };
+		14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndirectEvalExecutable.cpp; sourceTree = "<group>"; };
+		14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndirectEvalExecutable.h; sourceTree = "<group>"; };
 		1440051F0A531D3B0005F061 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = tests/Node.h; sourceTree = "<group>"; };
 		144005200A531D3B0005F061 /* Node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Node.c; path = tests/Node.c; sourceTree = "<group>"; };
 		144007480A536CC20005F061 /* NodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NodeList.h; path = tests/NodeList.h; sourceTree = "<group>"; };
@@ -6062,12 +6070,12 @@
 				F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */,
 				F692A84E0255597D01FF60F7 /* ArrayPrototype.h */,
 				0FB7F38A15ED8E3800F167B2 /* ArrayStorage.h */,
-				0F7CF9541DC1258B0098CC12 /* AtomicsObject.cpp */,
-				0F7CF9551DC1258B0098CC12 /* AtomicsObject.h */,
 				5B70CFDD1DB69E5C00EC23F9 /* AsyncFunctionConstructor.cpp */,
 				5B70CFDC1DB69E5C00EC23F9 /* AsyncFunctionConstructor.h */,
 				5B70CFDB1DB69E5C00EC23F9 /* AsyncFunctionPrototype.cpp */,
 				5B70CFDA1DB69E5C00EC23F9 /* AsyncFunctionPrototype.h */,
+				0F7CF9541DC1258B0098CC12 /* AtomicsObject.cpp */,
+				0F7CF9551DC1258B0098CC12 /* AtomicsObject.h */,
 				0F38D2A01D44196600680499 /* AuxiliaryBarrier.h */,
 				0F38D2A11D44196600680499 /* AuxiliaryBarrierInlines.h */,
 				52678F8C1A031009006A306D /* BasicBlockLocation.cpp */,
@@ -6136,6 +6144,8 @@
 				0FE050101AA9091100D33B33 /* DirectArguments.h */,
 				0FE0500D1AA9091100D33B33 /* DirectArgumentsOffset.cpp */,
 				0FE0500E1AA9091100D33B33 /* DirectArgumentsOffset.h */,
+				14386A721DD69895008652C4 /* DirectEvalExecutable.cpp */,
+				14386A731DD69895008652C4 /* DirectEvalExecutable.h */,
 				A70447EB17A0BD7000F5898E /* DumpContext.cpp */,
 				A70447EC17A0BD7000F5898E /* DumpContext.h */,
 				FE318FDD1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.cpp */,
@@ -6203,6 +6213,8 @@
 				0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
 				0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
 				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
+				14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */,
+				14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */,
 				0F0A75201B94BFA900110660 /* InferredType.cpp */,
 				0F0A75211B94BFA900110660 /* InferredType.h */,
 				0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
@@ -8413,6 +8425,7 @@
 				0F2B66EA17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h in Headers */,
 				BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */,
 				140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */,
+				14386A751DD69895008652C4 /* DirectEvalExecutable.h in Headers */,
 				86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
 				BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */,
 				BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */,
@@ -8771,6 +8784,7 @@
 				DC2143071CA32E55000A8869 /* ICStats.h in Headers */,
 				869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */,
 				70B0A9D11A9B66460001306A /* RuntimeFlags.h in Headers */,
+				14386A791DD6989C008652C4 /* IndirectEvalExecutable.h in Headers */,
 				52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */,
 				C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */,
 				0FE050281AA9095600D33B33 /* ScopedArguments.h in Headers */,
@@ -9648,6 +9662,7 @@
 				0FBF158C19B7A53100695DD0 /* DFGBlockSet.cpp in Sources */,
 				86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */,
 				0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */,
+				14386A741DD69895008652C4 /* DirectEvalExecutable.cpp in Sources */,
 				0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */,
 				0F3B3A271544C995003ED0FF /* DFGCFGSimplificationPhase.cpp in Sources */,
 				0F9D36941AE9CC33000D4DFB /* DFGCleanUpPhase.cpp in Sources */,
@@ -9793,6 +9808,7 @@
 				0FE254F61ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp in Sources */,
 				0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */,
 				0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */,
+				14386A781DD6989C008652C4 /* IndirectEvalExecutable.cpp in Sources */,
 				0F9495871C57F47500413A48 /* B3StackSlot.cpp in Sources */,
 				0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */,
 				AD2FCBF21DB58DAD00B3E736 /* WebAssemblyInstancePrototype.cpp in Sources */,
@@ -10098,7 +10114,6 @@
 				0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
 				A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */,
 				A5A1A0951D8CB341004C2EB8 /* DebuggerParseData.cpp in Sources */,
-				53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */,
 				FE3913541B794F6E00EDAF71 /* LiveObjectList.cpp in Sources */,
 				FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */,
 				0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (208711 => 208712)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -43,6 +43,7 @@
 #include "DFGExitProfile.h"
 #include "DeferredCompilationCallback.h"
 #include "EvalCodeCache.h"
+#include "EvalExecutable.h"
 #include "ExecutionCounter.h"
 #include "ExpressionRangeInfo.h"
 #include "FunctionExecutable.h"

Modified: trunk/Source/_javascript_Core/bytecode/EvalCodeCache.h (208711 => 208712)


--- trunk/Source/_javascript_Core/bytecode/EvalCodeCache.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/bytecode/EvalCodeCache.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -28,12 +28,7 @@
 
 #pragma once
 
-#include "EvalExecutable.h"
-#include "JSGlobalObject.h"
-#include "JSScope.h"
-#include "Options.h"
-#include "SourceCode.h"
-#include "SourceCodeKey.h"
+#include "DirectEvalExecutable.h"
 #include <wtf/HashMap.h>
 #include <wtf/RefPtr.h>
 #include <wtf/text/StringHash.h>
@@ -44,7 +39,6 @@
 
     class EvalCodeCache {
     public:
-        // Specialized cache key (compared with SourceCodeKey) for eval code cache.
         class CacheKey {
         public:
             CacheKey(const String& source, CallSiteIndex callSiteIndex)
@@ -90,23 +84,15 @@
             CallSiteIndex m_callSiteIndex;
         };
 
-        EvalExecutable* tryGet(const String& evalSource, CallSiteIndex callSiteIndex)
+        DirectEvalExecutable* tryGet(const String& evalSource, CallSiteIndex callSiteIndex)
         {
             return m_cacheMap.fastGet(CacheKey(evalSource, callSiteIndex)).get();
         }
         
-        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, const String& evalSource, CallSiteIndex callSiteIndex, bool inStrictContext, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext, JSScope* scope)
+        void set(ExecState* exec, JSCell* owner, const String& evalSource, CallSiteIndex callSiteIndex, DirectEvalExecutable* evalExecutable)
         {
-            VariableEnvironment variablesUnderTDZ;
-            JSScope::collectVariablesUnderTDZ(scope, variablesUnderTDZ);
-            EvalExecutable* evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, &variablesUnderTDZ);
-            if (!evalExecutable)
-                return nullptr;
-
             if (m_cacheMap.size() < maxCacheEntries)
-                m_cacheMap.set(CacheKey(evalSource, callSiteIndex), WriteBarrier<EvalExecutable>(exec->vm(), owner, evalExecutable));
-
-            return evalExecutable;
+                m_cacheMap.set(CacheKey(evalSource, callSiteIndex), WriteBarrier<DirectEvalExecutable>(exec->vm(), owner, evalExecutable));
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
@@ -121,7 +107,7 @@
     private:
         static const int maxCacheEntries = 64;
 
-        typedef HashMap<CacheKey, WriteBarrier<EvalExecutable>, CacheKey::Hash, CacheKey::HashTraits> EvalCacheMap;
+        typedef HashMap<CacheKey, WriteBarrier<DirectEvalExecutable>, CacheKey::Hash, CacheKey::HashTraits> EvalCacheMap;
         EvalCacheMap m_cacheMap;
     };
 

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedEvalCodeBlock.h (208711 => 208712)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedEvalCodeBlock.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedEvalCodeBlock.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -30,8 +30,9 @@
 namespace JSC {
 
 class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock {
-private:
-    friend class CodeCache;
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode)
     {
@@ -40,10 +41,6 @@
         return instance;
     }
 
-public:
-    typedef UnlinkedGlobalCodeBlock Base;
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
-
     static void destroy(JSCell*);
 
     const Identifier& variable(unsigned index) { return m_variables[index]; }

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -180,7 +180,7 @@
     ParserError error;
     VM& vm = exec.vm();
     CodeCache* codeCache = vm.codeCache();
-    UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(vm, name, source, error);
+    UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, error);
 
     auto& globalObject = *exec.lexicalGlobalObject();
     if (globalObject.hasDebugger())

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedModuleProgramCodeBlock.h (208711 => 208712)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedModuleProgramCodeBlock.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedModuleProgramCodeBlock.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -30,8 +30,10 @@
 namespace JSC {
 
 class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
-private:
-    friend class CodeCache;
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
     static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode)
     {
         UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedModuleProgramCodeBlock>(vm->heap)) UnlinkedModuleProgramCodeBlock(vm, vm->unlinkedModuleProgramCodeBlockStructure.get(), info, debuggerMode);
@@ -39,10 +41,6 @@
         return instance;
     }
 
-public:
-    typedef UnlinkedGlobalCodeBlock Base;
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
-
     static void destroy(JSCell*);
 
     static void visitChildren(JSCell*, SlotVisitor&);

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedProgramCodeBlock.h (208711 => 208712)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedProgramCodeBlock.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedProgramCodeBlock.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -30,8 +30,10 @@
 namespace JSC {
 
 class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
-private:
-    friend class CodeCache;
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode)
     {
         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info, debuggerMode);
@@ -39,10 +41,6 @@
         return instance;
     }
 
-public:
-    typedef UnlinkedGlobalCodeBlock Base;
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
-
     static void destroy(JSCell*);
 
     void setVariableDeclarations(const VariableEnvironment& environment) { m_varDeclarations = environment; }

Modified: trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -241,9 +241,9 @@
         evalContextType = EvalContextType::None;
 
     VariableEnvironment variablesUnderTDZ;
-    JSScope::collectVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ);
+    JSScope::collectClosureVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ);
 
-    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock->isStrictMode(), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), evalContextType, &variablesUnderTDZ);
+    EvalExecutable* eval = DirectEvalExecutable::create(callFrame, makeSource(script), codeBlock->isStrictMode(), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), evalContextType, &variablesUnderTDZ);
     if (UNLIKELY(catchScope.exception())) {
         exception = catchScope.exception();
         catchScope.clearException();

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -131,7 +131,7 @@
     else
         evalContextType = EvalContextType::None;
 
-    EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(programSource, callerCallSiteIndex);
+    DirectEvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(programSource, callerCallSiteIndex);
     if (!eval) {
         if (!callerCodeBlock->isStrictMode()) {
             if (programSource.is8Bit()) {
@@ -148,10 +148,13 @@
         // If the literal parser bailed, it should not have thrown exceptions.
         ASSERT(!scope.exception());
 
-        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, programSource, callerCallSiteIndex, callerCodeBlock->isStrictMode(), derivedContextType, evalContextType, isArrowFunctionContext, callerScopeChain);
-
+        VariableEnvironment variablesUnderTDZ;
+        JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ);
+        eval = DirectEvalExecutable::create(callFrame, makeSource(programSource), callerCodeBlock->isStrictMode(), derivedContextType, isArrowFunctionContext, evalContextType, &variablesUnderTDZ);
         if (!eval)
             return jsUndefined();
+
+        callerCodeBlock->evalCodeCache().set(callFrame, callerCodeBlock, programSource, callerCallSiteIndex, eval);
     }
 
     JSValue thisValue = callerFrame->thisValue();

Modified: trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/llint/LLIntOffsetsExtractor.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -29,14 +29,17 @@
 #include "CodeBlock.h"
 #include "CommonSlowPaths.h"
 #include "DirectArguments.h"
+#include "DirectEvalExecutable.h"
+#include "EvalExecutable.h"
 #include "Exception.h"
 #include "Heap.h"
+#include "IndirectEvalExecutable.h"
 #include "Interpreter.h"
 #include "JSArray.h"
 #include "JSArrayBufferView.h"
 #include "JSCell.h"
+#include "JSEnvironmentRecord.h"
 #include "JSFunction.h"
-#include "JSEnvironmentRecord.h"
 #include "JSGlobalObject.h"
 #include "JSModuleRecord.h"
 #include "JSObject.h"
@@ -52,13 +55,12 @@
 #include "StructureChain.h"
 #include "TypeProfiler.h"
 #include "TypeProfilerLog.h"
+#include "VM.h"
 #include "VMEntryRecord.h"
 #include "ValueProfile.h"
-#include "VM.h"
 #include "Watchdog.h"
 #include <wtf/text/StringImpl.h>
 
-
 namespace JSC {
 
 #define OFFLINE_ASM_OFFSETOF(clazz, field) (static_cast<unsigned>(OBJECT_OFFSETOF(clazz, field)))

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -26,14 +26,7 @@
 #include "config.h"
 #include "CodeCache.h"
 
-#include "BytecodeGenerator.h"
-#include "JSCInlines.h"
-#include "Parser.h"
-#include "StrongInlines.h"
-#include "UnlinkedCodeBlock.h"
-#include "UnlinkedEvalCodeBlock.h"
-#include "UnlinkedModuleProgramCodeBlock.h"
-#include "UnlinkedProgramCodeBlock.h"
+#include "IndirectEvalExecutable.h"
 
 namespace JSC {
 
@@ -55,45 +48,15 @@
     }
 }
 
-CodeCache::CodeCache()
-{
-}
-
-CodeCache::~CodeCache()
-{
-}
-
-template <typename T> struct CacheTypes { };
-
-template <> struct CacheTypes<UnlinkedProgramCodeBlock> {
-    typedef JSC::ProgramNode RootNode;
-    static const SourceCodeType codeType = SourceCodeType::ProgramType;
-    static const SourceParseMode parseMode = SourceParseMode::ProgramMode;
-};
-
-template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
-    typedef JSC::EvalNode RootNode;
-    static const SourceCodeType codeType = SourceCodeType::EvalType;
-    static const SourceParseMode parseMode = SourceParseMode::ProgramMode;
-};
-
-template <> struct CacheTypes<UnlinkedModuleProgramCodeBlock> {
-    typedef JSC::ModuleProgramNode RootNode;
-    static const SourceCodeType codeType = SourceCodeType::ModuleType;
-    static const SourceParseMode parseMode = SourceParseMode::ModuleEvaluateMode;
-};
-
 template <class UnlinkedCodeBlockType, class ExecutableType>
-UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
+UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType)
 {
     DerivedContextType derivedContextType = executable->derivedContextType();
     bool isArrowFunctionContext = executable->isArrowFunctionContext();
     SourceCodeKey key(source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, builtinMode, strictMode, scriptMode, derivedContextType, evalContextType, isArrowFunctionContext);
     SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
-    // FIXME: We should do something smart for TDZ instead of just disabling caching.
-    // https://bugs.webkit.org/show_bug.cgi?id=154010
-    bool canCache = debuggerMode == DebuggerOff && !vm.typeProfiler() && !vm.controlFlowProfiler() && !variablesUnderTDZ->size();
-    if (cache && canCache && Options::useCodeCache()) {
+    bool canCache = debuggerMode == DebuggerOff && !vm.typeProfiler() && !vm.controlFlowProfiler() && Options::useCodeCache();
+    if (cache && canCache) {
         UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
         unsigned firstLine = source.firstLine() + unlinkedCodeBlock->firstLine();
         unsigned lineCount = unlinkedCodeBlock->lineCount();
@@ -105,56 +68,32 @@
         source.provider()->setSourceMappingURLDirective(unlinkedCodeBlock->sourceMappingURLDirective());
         return unlinkedCodeBlock;
     }
-    typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
-    std::unique_ptr<RootNode> rootNode = parse<RootNode>(
-        &vm, source, Identifier(), builtinMode, strictMode, scriptMode, CacheTypes<UnlinkedCodeBlockType>::parseMode, SuperBinding::NotNeeded, error, nullptr, ConstructorKind::None, derivedContextType, evalContextType);
-    if (!rootNode)
-        return nullptr;
+    
+    VariableEnvironment variablesUnderTDZ;
+    UnlinkedCodeBlockType* unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, builtinMode, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
 
-    unsigned lineCount = rootNode->lastLine() - rootNode->firstLine();
-    unsigned startColumn = rootNode->startColumn() + 1;
-    bool endColumnIsOnStartLine = !lineCount;
-    unsigned unlinkedEndColumn = rootNode->endColumn();
-    unsigned endColumn = unlinkedEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
-    unsigned arrowContextFeature = executable->isArrowFunctionContext() ? ArrowFunctionContextFeature : 0;
-    executable->recordParse(rootNode->features() | arrowContextFeature, rootNode->hasCapturedVariables(), rootNode->firstLine(), rootNode->lastLine(), startColumn, endColumn);
+    if (unlinkedCodeBlock && canCache)
+        m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));
 
-    UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executable->executableInfo(), debuggerMode);
-    unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->firstLine() - source.firstLine(), lineCount, unlinkedEndColumn);
-    unlinkedCodeBlock->setSourceURLDirective(source.provider()->sourceURL());
-    unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURL());
-
-    error = BytecodeGenerator::generate(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, variablesUnderTDZ);
-
-    if (error.isValid())
-        return nullptr;
-
-    if (!canCache)
-        return unlinkedCodeBlock;
-
-    m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));
     return unlinkedCodeBlock;
 }
 
-UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error)
+UnlinkedProgramCodeBlock* CodeCache::getUnlinkedProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error)
 {
-    VariableEnvironment emptyParentTDZVariables;
-    return getGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, builtinMode, strictMode, JSParserScriptMode::Classic, debuggerMode, error, EvalContextType::None, &emptyParentTDZVariables);
+    return getUnlinkedGlobalCodeBlock<UnlinkedProgramCodeBlock>(vm, executable, source, builtinMode, strictMode, JSParserScriptMode::Classic, debuggerMode, error, EvalContextType::None);
 }
 
-UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
+UnlinkedEvalCodeBlock* CodeCache::getUnlinkedGlobalEvalCodeBlock(VM& vm, IndirectEvalExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType)
 {
-    return getGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, builtinMode, strictMode, JSParserScriptMode::Classic, debuggerMode, error, evalContextType, variablesUnderTDZ);
+    return getUnlinkedGlobalCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, builtinMode, strictMode, JSParserScriptMode::Classic, debuggerMode, error, evalContextType);
 }
 
-UnlinkedModuleProgramCodeBlock* CodeCache::getModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, DebuggerMode debuggerMode, ParserError& error)
+UnlinkedModuleProgramCodeBlock* CodeCache::getUnlinkedModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, DebuggerMode debuggerMode, ParserError& error)
 {
-    VariableEnvironment emptyParentTDZVariables;
-    return getGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, builtinMode, JSParserStrictMode::Strict, JSParserScriptMode::Module, debuggerMode, error, EvalContextType::None, &emptyParentTDZVariables);
+    return getUnlinkedGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, builtinMode, JSParserStrictMode::Strict, JSParserScriptMode::Module, debuggerMode, error, EvalContextType::None);
 }
 
-// FIXME: There's no need to add the function's name to the key here. It's already in the source code.
-UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error)
+UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error)
 {
     bool isArrowFunctionContext = false;
     SourceCodeKey key(

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.h (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/CodeCache.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -25,11 +25,19 @@
 
 #pragma once
 
+#include "BytecodeGenerator.h"
 #include "ExecutableInfo.h"
+#include "JSCInlines.h"
+#include "Parser.h"
 #include "ParserModes.h"
 #include "SourceCode.h"
 #include "SourceCodeKey.h"
 #include "Strong.h"
+#include "StrongInlines.h"
+#include "UnlinkedCodeBlock.h"
+#include "UnlinkedEvalCodeBlock.h"
+#include "UnlinkedModuleProgramCodeBlock.h"
+#include "UnlinkedProgramCodeBlock.h"
 #include <wtf/CurrentTime.h>
 #include <wtf/Forward.h>
 #include <wtf/text/WTFString.h>
@@ -37,7 +45,9 @@
 namespace JSC {
 
 class EvalExecutable;
+class IndirectEvalExecutable;
 class Identifier;
+class DirectEvalExecutable;
 class ModuleProgramExecutable;
 class ParserError;
 class ProgramExecutable;
@@ -179,28 +189,73 @@
     int64_t m_age;
 };
 
-// Caches top-level code such as <script>, eval(), new Function, and JSEvaluateScript().
+// Caches top-level code such as <script>, window.eval(), new Function, and JSEvaluateScript().
 class CodeCache {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    CodeCache();
-    ~CodeCache();
+    UnlinkedProgramCodeBlock* getUnlinkedProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ParserError&);
+    UnlinkedEvalCodeBlock* getUnlinkedGlobalEvalCodeBlock(VM&, IndirectEvalExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ParserError&, EvalContextType);
+    UnlinkedModuleProgramCodeBlock* getUnlinkedModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, JSParserBuiltinMode, DebuggerMode, ParserError&);
+    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, ParserError&);
 
-    UnlinkedProgramCodeBlock* getProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ParserError&);
-    UnlinkedEvalCodeBlock* getEvalCodeBlock(VM&, EvalExecutable*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, DebuggerMode, ParserError&, EvalContextType, const VariableEnvironment*);
-    UnlinkedModuleProgramCodeBlock* getModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, JSParserBuiltinMode, DebuggerMode, ParserError&);
-    UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(VM&, const Identifier&, const SourceCode&, ParserError&);
+    void clear() { m_sourceCode.clear(); }
 
-    void clear()
-    {
-        m_sourceCode.clear();
-    }
-
 private:
     template <class UnlinkedCodeBlockType, class ExecutableType> 
-    UnlinkedCodeBlockType* getGlobalCodeBlock(VM&, ExecutableType*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, JSParserScriptMode, DebuggerMode, ParserError&, EvalContextType, const VariableEnvironment*);
+    UnlinkedCodeBlockType* getUnlinkedGlobalCodeBlock(VM&, ExecutableType*, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, JSParserScriptMode, DebuggerMode, ParserError&, EvalContextType);
 
     CodeCacheMap m_sourceCode;
 };
 
+template <typename T> struct CacheTypes { };
+
+template <> struct CacheTypes<UnlinkedProgramCodeBlock> {
+    typedef JSC::ProgramNode RootNode;
+    static const SourceCodeType codeType = SourceCodeType::ProgramType;
+    static const SourceParseMode parseMode = SourceParseMode::ProgramMode;
+};
+
+template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
+    typedef JSC::EvalNode RootNode;
+    static const SourceCodeType codeType = SourceCodeType::EvalType;
+    static const SourceParseMode parseMode = SourceParseMode::ProgramMode;
+};
+
+template <> struct CacheTypes<UnlinkedModuleProgramCodeBlock> {
+    typedef JSC::ModuleProgramNode RootNode;
+    static const SourceCodeType codeType = SourceCodeType::ModuleType;
+    static const SourceParseMode parseMode = SourceParseMode::ModuleEvaluateMode;
+};
+
+template <class UnlinkedCodeBlockType, class ExecutableType>
+UnlinkedCodeBlockType* generateUnlinkedCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
+{
+    typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
+    DerivedContextType derivedContextType = executable->derivedContextType();
+    std::unique_ptr<RootNode> rootNode = parse<RootNode>(
+        &vm, source, Identifier(), builtinMode, strictMode, scriptMode, CacheTypes<UnlinkedCodeBlockType>::parseMode, SuperBinding::NotNeeded, error, nullptr, ConstructorKind::None, derivedContextType, evalContextType);
+    if (!rootNode)
+        return nullptr;
+
+    unsigned lineCount = rootNode->lastLine() - rootNode->firstLine();
+    unsigned startColumn = rootNode->startColumn() + 1;
+    bool endColumnIsOnStartLine = !lineCount;
+    unsigned unlinkedEndColumn = rootNode->endColumn();
+    unsigned endColumn = unlinkedEndColumn + (endColumnIsOnStartLine ? startColumn : 1);
+    unsigned arrowContextFeature = executable->isArrowFunctionContext() ? ArrowFunctionContextFeature : 0;
+    executable->recordParse(rootNode->features() | arrowContextFeature, rootNode->hasCapturedVariables(), rootNode->firstLine(), rootNode->lastLine(), startColumn, endColumn);
+
+    UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executable->executableInfo(), debuggerMode);
+    unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->firstLine() - source.firstLine(), lineCount, unlinkedEndColumn);
+    unlinkedCodeBlock->setSourceURLDirective(source.provider()->sourceURL());
+    unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURL());
+
+    error = BytecodeGenerator::generate(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, variablesUnderTDZ);
+
+    if (error.isValid())
+        return nullptr;
+
+    return unlinkedCodeBlock;
+}
+
 } // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.cpp (0 => 208712)


--- trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 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 "DirectEvalExecutable.h"
+
+#include "Error.h"
+#include "HeapInlines.h"
+#include "JSCJSValueInlines.h"
+
+namespace JSC {
+
+DirectEvalExecutable* DirectEvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    if (!globalObject->evalEnabled()) {
+        throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
+        return 0;
+    }
+
+    auto* executable = new (NotNull, allocateCell<DirectEvalExecutable>(*exec->heap())) DirectEvalExecutable(exec, source, isInStrictContext, derivedContextType, isArrowFunctionContext, evalContextType);
+    executable->finishCreation(vm);
+
+    UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createLocalEvalCodeBlock(exec, executable, variablesUnderTDZ);
+    if (!unlinkedEvalCode)
+        return 0;
+
+    executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
+
+    return executable;
+}
+
+DirectEvalExecutable::DirectEvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
+    : EvalExecutable(exec, source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType)
+{
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.h (0 => 208712)


--- trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/DirectEvalExecutable.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 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. 
+ */
+
+#pragma once
+
+#include "EvalExecutable.h"
+
+namespace JSC {
+
+class DirectEvalExecutable final : public EvalExecutable {
+public:
+    static DirectEvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*);
+private:
+    DirectEvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/EvalExecutable.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/EvalExecutable.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/EvalExecutable.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -24,47 +24,17 @@
  */
 
 #include "config.h"
+#include "EvalExecutable.h"
 
-#include "BatchedTransitionOptimizer.h"
-#include "CodeBlock.h"
-#include "Debugger.h"
 #include "EvalCodeBlock.h"
-#include "FunctionCodeBlock.h"
-#include "JIT.h"
-#include "JSCInlines.h"
-#include "LLIntEntrypoint.h"
-#include "Parser.h"
-#include "TypeProfiler.h"
-#include "VMInlines.h"
-#include <wtf/CommaPrinter.h>
+#include "HeapCellInlines.h"
+#include "JSCJSValueInlines.h"
+#include "SlotVisitorInlines.h"
 
 namespace JSC {
 
 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };
 
-EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)
-{
-    VM& vm = exec->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    if (!globalObject->evalEnabled()) {
-        throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
-        return 0;
-    }
-
-    EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext, derivedContextType, isArrowFunctionContext, evalContextType);
-    executable->finishCreation(vm);
-
-    UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, variablesUnderTDZ);
-    if (!unlinkedEvalCode)
-        return 0;
-
-    executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
-
-    return executable;
-}
-
 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, NoIntrinsic)
 {

Modified: trunk/Source/_javascript_Core/runtime/EvalExecutable.h (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/EvalExecutable.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/EvalExecutable.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -30,7 +30,7 @@
 
 namespace JSC {
 
-class EvalExecutable final : public ScriptExecutable {
+class EvalExecutable : public ScriptExecutable {
     friend class LLIntOffsetsExtractor;
 public:
     typedef ScriptExecutable Base;
@@ -43,8 +43,6 @@
         return m_evalCodeBlock.get();
     }
 
-    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*);
-
     PassRefPtr<JITCode> generatedJITCode()
     {
         return generatedJITCodeForCall();
@@ -54,7 +52,7 @@
     {
         return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
     }
-        
+
     DECLARE_INFO;
 
     ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); }
@@ -62,10 +60,11 @@
     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
 
-private:
+protected:
     friend class ExecutableBase;
     friend class ScriptExecutable;
 
+    using Base::finishCreation;
     EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
 
     static void visitChildren(JSCell*, SlotVisitor&);

Added: trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp (0 => 208712)


--- trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 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 "IndirectEvalExecutable.h"
+
+#include "Error.h"
+#include "HeapInlines.h"
+#include "JSCJSValueInlines.h"
+
+namespace JSC {
+
+IndirectEvalExecutable* IndirectEvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    if (!globalObject->evalEnabled()) {
+        throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
+        return 0;
+    }
+
+    auto* executable = new (NotNull, allocateCell<IndirectEvalExecutable>(*exec->heap())) IndirectEvalExecutable(exec, source, isInStrictContext, derivedContextType, isArrowFunctionContext, evalContextType);
+    executable->finishCreation(vm);
+
+    UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createGlobalEvalCodeBlock(exec, executable);
+    if (!unlinkedEvalCode)
+        return 0;
+
+    executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);
+
+    return executable;
+}
+
+IndirectEvalExecutable::IndirectEvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
+    : EvalExecutable(exec, source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType)
+{
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h (0 => 208712)


--- trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 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. 
+ */
+
+#pragma once
+
+#include "EvalExecutable.h"
+
+namespace JSC {
+
+class IndirectEvalExecutable final : public EvalExecutable {
+public:
+    static IndirectEvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
+private:
+    IndirectEvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -49,6 +49,7 @@
 #include "Debugger.h"
 #include "DebuggerScope.h"
 #include "DirectArguments.h"
+#include "DirectEvalExecutable.h"
 #include "ECMAScriptSpecInternalFunctions.h"
 #include "Error.h"
 #include "ErrorConstructor.h"
@@ -60,6 +61,7 @@
 #include "GeneratorPrototype.h"
 #include "GetterSetter.h"
 #include "HeapIterationScope.h"
+#include "IndirectEvalExecutable.h"
 #include "InspectorInstrumentationObject.h"
 #include "Interpreter.h"
 #include "IteratorPrototype.h"
@@ -1317,7 +1319,7 @@
     ParserError error;
     JSParserStrictMode strictMode = executable->isStrictMode() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict;
     DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
-    UnlinkedProgramCodeBlock* unlinkedCodeBlock = vm().codeCache()->getProgramCodeBlock(
+    UnlinkedProgramCodeBlock* unlinkedCodeBlock = vm().codeCache()->getUnlinkedProgramCodeBlock(
         vm(), executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, 
         debuggerMode, error);
 
@@ -1332,7 +1334,7 @@
     return unlinkedCodeBlock;
 }
 
-UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame, EvalExecutable* executable, const VariableEnvironment* variablesUnderTDZ)
+UnlinkedEvalCodeBlock* JSGlobalObject::createLocalEvalCodeBlock(CallFrame* callFrame, DirectEvalExecutable* executable, const VariableEnvironment* variablesUnderTDZ)
 {
     VM& vm = this->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -1341,9 +1343,34 @@
     JSParserStrictMode strictMode = executable->isStrictMode() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict;
     DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
     EvalContextType evalContextType = executable->executableInfo().evalContextType();
+
+    // We don't bother with CodeCache here because local eval uses a specialized EvalCodeCache.
+    UnlinkedEvalCodeBlock* unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedEvalCodeBlock>(
+        vm, executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, JSParserScriptMode::Classic, debuggerMode, error, evalContextType, variablesUnderTDZ);
+
+    if (hasDebugger())
+        debugger()->sourceParsed(callFrame, executable->source().provider(), error.line(), error.message());
+
+    if (error.isValid()) {
+        throwVMError(callFrame, scope, error.toErrorObject(this, executable->source()));
+        return nullptr;
+    }
+
+    return unlinkedCodeBlock;
+}
+
+UnlinkedEvalCodeBlock* JSGlobalObject::createGlobalEvalCodeBlock(CallFrame* callFrame, IndirectEvalExecutable* executable)
+{
+    VM& vm = this->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    ParserError error;
+    JSParserStrictMode strictMode = executable->isStrictMode() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict;
+    DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
+    EvalContextType evalContextType = executable->executableInfo().evalContextType();
     
-    UnlinkedEvalCodeBlock* unlinkedCodeBlock = vm.codeCache()->getEvalCodeBlock(
-        vm, executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, debuggerMode, error, evalContextType, variablesUnderTDZ);
+    UnlinkedEvalCodeBlock* unlinkedCodeBlock = vm.codeCache()->getUnlinkedGlobalEvalCodeBlock(
+        vm, executable, executable->source(), JSParserBuiltinMode::NotBuiltin, strictMode, debuggerMode, error, evalContextType);
 
     if (hasDebugger())
         debugger()->sourceParsed(callFrame, executable->source().provider(), error.line(), error.message());
@@ -1363,7 +1390,7 @@
 
     ParserError error;
     DebuggerMode debuggerMode = hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
-    UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = vm.codeCache()->getModuleProgramCodeBlock(
+    UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = vm.codeCache()->getUnlinkedModuleProgramCodeBlock(
         vm, executable, executable->source(), JSParserBuiltinMode::NotBuiltin, debuggerMode, error);
 
     if (hasDebugger())

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -71,6 +71,7 @@
 class GeneratorFunctionPrototype;
 class GetterSetter;
 class GlobalCodeBlock;
+class IndirectEvalExecutable;
 class InputCursor;
 class JSArrayBuffer;
 class JSArrayBufferConstructor;
@@ -86,6 +87,7 @@
 class JSSharedArrayBufferPrototype;
 class JSTypedArrayViewConstructor;
 class JSTypedArrayViewPrototype;
+class DirectEvalExecutable;
 class LLIntOffsetsExtractor;
 class Microtask;
 class ModuleLoaderPrototype;
@@ -827,7 +829,8 @@
     WeakRandom& weakRandom() { return m_weakRandom; }
 
     UnlinkedProgramCodeBlock* createProgramCodeBlock(CallFrame*, ProgramExecutable*, JSObject** exception);
-    UnlinkedEvalCodeBlock* createEvalCodeBlock(CallFrame*, EvalExecutable*, const VariableEnvironment*);
+    UnlinkedEvalCodeBlock* createLocalEvalCodeBlock(CallFrame*, DirectEvalExecutable*, const VariableEnvironment*);
+    UnlinkedEvalCodeBlock* createGlobalEvalCodeBlock(CallFrame*, IndirectEvalExecutable*);
     UnlinkedModuleProgramCodeBlock* createModuleProgramCodeBlock(CallFrame*, ModuleProgramExecutable*);
 
     bool needsSiteSpecificQuirks() const { return m_needsSiteSpecificQuirks; }

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -27,6 +27,7 @@
 
 #include "CallFrame.h"
 #include "EvalExecutable.h"
+#include "IndirectEvalExecutable.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
@@ -680,8 +681,7 @@
     }
 
     JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject();
-    VariableEnvironment emptyTDZVariables; // Indirect eval does not have access to the lexical scope.
-    EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false, DerivedContextType::None, false, EvalContextType::None, &emptyTDZVariables);
+    EvalExecutable* eval = IndirectEvalExecutable::create(exec, makeSource(s), false, DerivedContextType::None, false, EvalContextType::None);
     if (!eval)
         return JSValue::encode(jsUndefined());
 

Modified: trunk/Source/_javascript_Core/runtime/JSScope.cpp (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/JSScope.cpp	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/JSScope.cpp	2016-11-14 22:57:12 UTC (rev 208712)
@@ -263,10 +263,10 @@
     return op;
 }
 
-void JSScope::collectVariablesUnderTDZ(JSScope* scope, VariableEnvironment& result)
+void JSScope::collectClosureVariablesUnderTDZ(JSScope* scope, VariableEnvironment& result)
 {
     for (; scope; scope = scope->next()) {
-        if (!scope->isLexicalScope() && !scope->isGlobalLexicalEnvironment() && !scope->isCatchScope())
+        if (!scope->isLexicalScope() && !scope->isCatchScope())
             continue;
 
         if (scope->isModuleScope()) {
@@ -276,7 +276,7 @@
         }
 
         SymbolTable* symbolTable = jsCast<JSSymbolTableObject*>(scope)->symbolTable();
-        ASSERT(symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope || symbolTable->scopeType() == SymbolTable::ScopeType::GlobalLexicalScope || symbolTable->scopeType() == SymbolTable::ScopeType::CatchScope);
+        ASSERT(symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope || symbolTable->scopeType() == SymbolTable::ScopeType::CatchScope);
         ConcurrentJITLocker locker(symbolTable->m_lock);
         for (auto end = symbolTable->end(locker), iter = symbolTable->begin(locker); iter != end; ++iter)
             result.add(iter->key);

Modified: trunk/Source/_javascript_Core/runtime/JSScope.h (208711 => 208712)


--- trunk/Source/_javascript_Core/runtime/JSScope.h	2016-11-14 22:54:09 UTC (rev 208711)
+++ trunk/Source/_javascript_Core/runtime/JSScope.h	2016-11-14 22:57:12 UTC (rev 208712)
@@ -51,7 +51,7 @@
     static bool hasConstantScope(ResolveType);
     static JSScope* constantScopeForCodeBlock(ResolveType, CodeBlock*);
 
-    static void collectVariablesUnderTDZ(JSScope*, VariableEnvironment& result);
+    static void collectClosureVariablesUnderTDZ(JSScope*, VariableEnvironment& result);
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to