Reduce parser overhead in JSC
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Nov 2012 00:13:54 +0000 (00:13 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Nov 2012 00:13:54 +0000 (00:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=101127

Reviewed by Filip Pizlo.

An exciting journey into the world of architecture in which our hero
adds yet another layer to JSC codegeneration.

This patch adds a marginally more compact form of bytecode that is
free from any data specific to a given execution context, and that
does store any data structures necessary for execution.  To actually
execute this UnlinkedBytecode we still need to instantiate a real
CodeBlock, but this is a much faster linear time operation than any
of the earlier parsing or code generation passes.

As the unlinked code is context free we can then simply use a cache
from source to unlinked code mapping to completely avoid all of the
old parser overhead.  The cache is currently very simple and memory
heavy, using the complete source text as a key (rather than SourceCode
or equivalent), and a random eviction policy.

This seems to produce a substantial win when loading identical content
in different contexts.

* API/tests/testapi.c:
(main):
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
* bytecode/CodeBlock.h:
    Moved a number of fields, and a bunch of logic to UnlinkedCodeBlock.h/cpp
* bytecode/Opcode.h:
    Added a global const init no op instruction needed to get correct
    behaviour without any associated semantics.
* bytecode/UnlinkedCodeBlock.cpp: Added.
* bytecode/UnlinkedCodeBlock.h: Added.
    A fairly shallow, GC allocated version of the old CodeBlock
    classes with a 32bit instruction size, and just metadata
    size tracking.
* bytecompiler/BytecodeGenerator.cpp:
* bytecompiler/BytecodeGenerator.h:
    Replace direct access to m_symbolTable with access through
    symbolTable().  ProgramCode no longer has a symbol table at
    all so some previously unconditional (and pointless) uses
    of symbolTable get null checks.
    A few other changes to deal with type changes due to us generating
    unlinked code (eg. pointer free, so profile indices rather than
    pointers).
* dfg/DFGByteCodeParser.cpp:
* dfg/DFGCapabilities.h:
    Support global_init_nop
* interpreter/Interpreter.cpp:
    Now get the ProgramExecutable to initialise new global properties
    before starting execution.
* jit/JIT.cpp:
* jit/JITDriver.h:
* jit/JITStubs.cpp:
* llint/LLIntData.cpp:
* llint/LLIntSlowPaths.cpp:
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
    Adding init_global_const_nop everywhere else
* parser/Parser.h:
* parser/ParserModes.h: Added.
* parser/ParserTokens.h:
    Parser no longer needs a global object or callframe to function
* runtime/CodeCache.cpp: Added.
* runtime/CodeCache.h: Added.
    A simple, random eviction, Source->UnlinkedCode cache
* runtime/Executable.cpp:
* runtime/Executable.h:
    Executables now reference their unlinked counterparts, and
    request code specifically for the target global object.
* runtime/JSGlobalData.cpp:
* runtime/JSGlobalData.h:
    GlobalData now owns a CodeCache and a set of new structures
    for the unlinked code types.
* runtime/JSGlobalObject.cpp:
* runtime/JSGlobalObject.h:
    Utility functions used by executables to perform compilation

* runtime/JSType.h:
  Add new JSTypes for unlinked code

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@133688 268f45cc-cd09-0410-ab3c-d52691b4dbfc

50 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/Opcode.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp [new file with mode: 0644]
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h [new file with mode: 0644]
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/dfg/DFGByteCodeCache.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/MarkedAllocator.h
Source/JavaScriptCore/heap/SlotVisitor.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITDriver.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/jit/JITStubs.h
Source/JavaScriptCore/llint/LLIntData.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.h
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserModes.h [new file with mode: 0644]
Source/JavaScriptCore/parser/ParserTokens.h
Source/JavaScriptCore/runtime/Arguments.h
Source/JavaScriptCore/runtime/CodeCache.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/CodeCache.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/ExecutionHarness.h
Source/JavaScriptCore/runtime/JSActivation.h
Source/JavaScriptCore/runtime/JSGlobalData.cpp
Source/JavaScriptCore/runtime/JSGlobalData.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSType.h

index 754f304668e311d47d09ea4e7940b7849aa03b0d..393db67c3b21883e547293fceb4b0979d38664be 100644 (file)
@@ -59,6 +59,7 @@ SET(JavaScriptCore_SOURCES
     bytecode/SpecialPointer.cpp
     bytecode/StructureStubClearingWatchpoint.cpp
     bytecode/StructureStubInfo.cpp
+    bytecode/UnlinkedCodeBlock.cpp
     bytecode/Watchpoint.cpp
 
     bytecompiler/BytecodeGenerator.cpp
@@ -174,6 +175,7 @@ SET(JavaScriptCore_SOURCES
     runtime/BooleanObject.cpp
     runtime/BooleanPrototype.cpp
     runtime/CallData.cpp
+    runtime/CodeCache.cpp
     runtime/CommonIdentifiers.cpp
     runtime/Completion.cpp
     runtime/ConstructData.cpp
index 977a9b7547ec8fc803e4e006166ffd7817a5dd2f..8479ac59920cc9127729f5d2bd84835b3d1e02f0 100644 (file)
@@ -1,3 +1,92 @@
+2012-11-06  Oliver Hunt  <oliver@apple.com>
+
+        Reduce parser overhead in JSC
+        https://bugs.webkit.org/show_bug.cgi?id=101127
+
+        Reviewed by Filip Pizlo.
+
+        An exciting journey into the world of architecture in which our hero
+        adds yet another layer to JSC codegeneration.
+
+        This patch adds a marginally more compact form of bytecode that is
+        free from any data specific to a given execution context, and that
+        does store any data structures necessary for execution.  To actually
+        execute this UnlinkedBytecode we still need to instantiate a real
+        CodeBlock, but this is a much faster linear time operation than any
+        of the earlier parsing or code generation passes.
+
+        As the unlinked code is context free we can then simply use a cache
+        from source to unlinked code mapping to completely avoid all of the
+        old parser overhead.  The cache is currently very simple and memory
+        heavy, using the complete source text as a key (rather than SourceCode
+        or equivalent), and a random eviction policy.
+
+        This seems to produce a substantial win when loading identical content
+        in different contexts.
+
+        * API/tests/testapi.c:
+        (main):
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        * bytecode/CodeBlock.h:
+            Moved a number of fields, and a bunch of logic to UnlinkedCodeBlock.h/cpp
+        * bytecode/Opcode.h:
+            Added a global const init no op instruction needed to get correct
+            behaviour without any associated semantics.
+        * bytecode/UnlinkedCodeBlock.cpp: Added.
+        * bytecode/UnlinkedCodeBlock.h: Added.
+            A fairly shallow, GC allocated version of the old CodeBlock
+            classes with a 32bit instruction size, and just metadata
+            size tracking.
+        * bytecompiler/BytecodeGenerator.cpp:
+        * bytecompiler/BytecodeGenerator.h:
+            Replace direct access to m_symbolTable with access through
+            symbolTable().  ProgramCode no longer has a symbol table at
+            all so some previously unconditional (and pointless) uses
+            of symbolTable get null checks.
+            A few other changes to deal with type changes due to us generating
+            unlinked code (eg. pointer free, so profile indices rather than
+            pointers).
+        * dfg/DFGByteCodeParser.cpp:
+        * dfg/DFGCapabilities.h:
+            Support global_init_nop        
+        * interpreter/Interpreter.cpp:
+            Now get the ProgramExecutable to initialise new global properties
+            before starting execution.        
+        * jit/JIT.cpp:
+        * jit/JITDriver.h:
+        * jit/JITStubs.cpp:
+        * llint/LLIntData.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+            Adding init_global_const_nop everywhere else
+        * parser/Parser.h:
+        * parser/ParserModes.h: Added.
+        * parser/ParserTokens.h:
+            Parser no longer needs a global object or callframe to function        
+        * runtime/CodeCache.cpp: Added.
+        * runtime/CodeCache.h: Added.
+            A simple, random eviction, Source->UnlinkedCode cache        
+        * runtime/Executable.cpp:
+        * runtime/Executable.h:
+            Executables now reference their unlinked counterparts, and
+            request code specifically for the target global object.        
+        * runtime/JSGlobalData.cpp:
+        * runtime/JSGlobalData.h:
+            GlobalData now owns a CodeCache and a set of new structures
+            for the unlinked code types.  
+        * runtime/JSGlobalObject.cpp:
+        * runtime/JSGlobalObject.h:
+            Utility functions used by executables to perform compilation
+        * runtime/JSType.h:
+          Add new JSTypes for unlinked code
+
 2012-11-06  Michael Saboff  <msaboff@apple.com>
 
         JSStringCreateWithCFString() Should create an 8 bit String if possible
         (JSC::JIT::emit_op_next_pname):
         (JSC::JIT::compileOpStrictEq):
         (JSC::JIT::emit_op_catch):
-        (JSC::JIT::emit_op_throw_reference_error):
+        (JSC::JIT::emit_op_throw_static_error):
         (JSC::JIT::emit_op_eq_null):
         (JSC::JIT::emit_op_neq_null):
         (JSC::JIT::emit_op_create_activation):
index 457cce8d8522df00f5f6c81ce8e3e0b9f718e159..d68a22b9f714a41c276a480def7b7f9ac4aac78e 100644 (file)
@@ -138,6 +138,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/bytecode/StructureStubInfo.h \
        Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp \
        Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h \
+       Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp \
+       Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h \
        Source/JavaScriptCore/bytecode/ValueProfile.h \
        Source/JavaScriptCore/bytecode/ValueRecovery.h \
        Source/JavaScriptCore/bytecode/VirtualRegister.h \
@@ -444,6 +446,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/parser/ParserTokens.h \
        Source/JavaScriptCore/parser/Parser.cpp \
        Source/JavaScriptCore/parser/Parser.h \
+       Source/JavaScriptCore/parser/ParserModes.h \
        Source/JavaScriptCore/parser/ResultType.h \
        Source/JavaScriptCore/parser/SourceCode.h \
        Source/JavaScriptCore/parser/SourceProvider.h \
@@ -484,6 +487,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/CallData.cpp \
        Source/JavaScriptCore/runtime/CallData.h \
        Source/JavaScriptCore/runtime/ClassInfo.h \
+       Source/JavaScriptCore/runtime/CodeCache.cpp \
+       Source/JavaScriptCore/runtime/CodeCache.h \
        Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
        Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
        Source/JavaScriptCore/runtime/CommonIdentifiers.h \
index 0481e1bd52aea869ec48239cb672eba990434a21..c63231c2c7b25e20fd66fc9badfd7e2d7ab42e97 100644 (file)
                                RelativePath="..\..\runtime\ClassInfo.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\runtime\CodeCache.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\runtime\CodeCache.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\runtime\CommonIdentifiers.cpp"
                                >
                                RelativePath="..\..\bytecode\StructureStubInfo.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\bytecode\UnlinkedCodeBlock.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\bytecode\UnlinkedCodeBlock.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\bytecode\ValueProfile.h"
                                >
                                RelativePath="..\..\parser\Parser.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\parser\ParserModes.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\parser\ParserArena.cpp"
                                >
index 539efe28cceac8609e8e741d13b8a00232d7fd8b..3cada1cd7ceffb927acdb7a838051e0b1578af45 100644 (file)
                A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; };
                A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A76F279415F13C9600517D67 /* UnlinkedCodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */; };
                A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */; };
+               A77F1821164088B200640A47 /* CodeCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A77F181F164088B200640A47 /* CodeCache.cpp */; };
+               A77F1822164088B200640A47 /* CodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A77F1820164088B200640A47 /* CodeCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A77F1825164192C700640A47 /* ParserModes.h in Headers */ = {isa = PBXBuildFile; fileRef = A77F18241641925400640A47 /* ParserModes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A784A26111D16622005776AC /* ASTBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */; };
                A784A26411D16622005776AC /* SyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */; };
                A7AFC17915F7EFE30048F57B /* ResolveOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = A7AFC17715F7EFE30048F57B /* ResolveOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; };
                A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7B601821639FD2A00372BA3 /* UnlinkedCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */; };
                A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DCB77912E3D90500911940 /* WriteBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E2EA690FB460CF00601F06 /* LiteralParser.h */; };
                A767FF9F14F4502900789059 /* JSCTypedArrayStubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCTypedArrayStubs.h; sourceTree = "<group>"; };
                A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; };
                A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITWriteBarrier.h; sourceTree = "<group>"; };
+               A77F181F164088B200640A47 /* CodeCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeCache.cpp; sourceTree = "<group>"; };
+               A77F1820164088B200640A47 /* CodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeCache.h; sourceTree = "<group>"; };
+               A77F18241641925400640A47 /* ParserModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParserModes.h; sourceTree = "<group>"; };
+               A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedCodeBlock.cpp; sourceTree = "<group>"; };
+               A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedCodeBlock.h; sourceTree = "<group>"; };
                A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRefPrivate.h; sourceTree = "<group>"; };
                A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTBuilder.h; sourceTree = "<group>"; };
                A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyntaxChecker.h; sourceTree = "<group>"; };
                                E49DC15112EF272200184A1F /* SourceProviderCache.h */,
                                E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */,
                                A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */,
+                               A77F18241641925400640A47 /* ParserModes.h */,
                        );
                        path = parser;
                        sourceTree = "<group>";
                                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
                                A7DCB77912E3D90500911940 /* WriteBarrier.h */,
                                C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */,
+                               A77F181F164088B200640A47 /* CodeCache.cpp */,
+                               A77F1820164088B200640A47 /* CodeCache.h */,
                        );
                        path = runtime;
                        sourceTree = "<group>";
                                0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
                                0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
                                0F93329B14CA7DC10085F3C6 /* StructureSet.h */,
+                               A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */,
+                               A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */,
                        );
                        path = bytecode;
                        sourceTree = "<group>";
                                0FEB3ECD16237F4D00AB67AD /* TypedArrayDescriptor.h in Headers */,
                                0F256C361627B0AD007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h in Headers */,
                                C2239D1B16262BDD005AC5FD /* GCThread.h in Headers */,
+                               A7B601821639FD2A00372BA3 /* UnlinkedCodeBlock.h in Headers */,
+                               A77F1822164088B200640A47 /* CodeCache.h in Headers */,
+                               A77F1825164192C700640A47 /* ParserModes.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */,
                                C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
                                C2239D1A16262BDD005AC5FD /* GCThread.cpp in Sources */,
+                               A76F279415F13C9600517D67 /* UnlinkedCodeBlock.cpp in Sources */,
+                               A77F1821164088B200640A47 /* CodeCache.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 186a54b4ee6199e8d5f5e698d5690591aa0c462f..b0fcc16e7c5bf55ba477dff10399cbc114a7682b 100644 (file)
@@ -69,6 +69,7 @@ SOURCES += \
     bytecode/SpeculatedType.cpp \
     bytecode/StructureStubClearingWatchpoint.cpp \
     bytecode/StructureStubInfo.cpp \
+    bytecode/UnlinkedCodeBlock.cpp \
     bytecode/Watchpoint.cpp \
     bytecompiler/BytecodeGenerator.cpp \
     bytecompiler/NodesCodegen.cpp \
@@ -184,6 +185,7 @@ SOURCES += \
     runtime/BooleanObject.cpp \
     runtime/BooleanPrototype.cpp \
     runtime/CallData.cpp \
+    runtime/CodeCache.cpp \
     runtime/CommonIdentifiers.cpp \
     runtime/Completion.cpp \
     runtime/ConstructData.cpp \
index 24f747a9c729cf0caf583a6a7c2cfc7d43c3ebde..ceae3fcb255495e1c4cfb0265cfecf0e6078482b 100644 (file)
@@ -527,13 +527,13 @@ void CodeBlock::dump(ExecState* exec)
         } while (i < m_constantRegisters.size());
     }
 
-    if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
+    if (size_t count = m_unlinkedCode->numberOfRegExps()) {
         dataLog("\nm_regexps:\n");
         size_t i = 0;
         do {
-            dataLog("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).utf8().data());
+            dataLog("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).utf8().data());
             ++i;
-        } while (i < m_rareData->m_regexps.size());
+        } while (i < count);
     }
 
 #if ENABLE(JIT)
@@ -667,7 +667,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int dst = (++it)->u.operand;
             int argv = (++it)->u.operand;
             int argc = (++it)->u.operand;
-            dataLog("[%4d] new_array_buffer %s, %d, %d", location, registerName(exec, dst).data(), argv, argc);
+            dataLog("[%4d] new_array_buffer\t %s, %d, %d", location, registerName(exec, dst).data(), argv, argc);
             dumpBytecodeCommentAndNewLine(location);
             break;
         }
@@ -675,7 +675,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r0 = (++it)->u.operand;
             int re0 = (++it)->u.operand;
             dataLog("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data());
-            if (r0 >=0 && r0 < (int)numberOfRegExps())
+            if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps())
                 dataLog("%s", regexpName(re0, regexp(re0)).data());
             else
                 dataLog("bad_regexp(%d)", re0);
@@ -885,11 +885,22 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             it++;
             break;
         }
+        case op_init_global_const_nop: {
+            dataLog("[%4d] init_global_const_nop\t", location);
+            dumpBytecodeCommentAndNewLine(location);
+            it++;
+            it++;
+            it++;
+            it++;
+            break;
+        }
         case op_init_global_const: {
             WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
             int r0 = (++it)->u.operand;
             dataLog("[%4d] init_global_const\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data());
             dumpBytecodeCommentAndNewLine(location);
+            it++;
+            it++;
             break;
         }
         case op_init_global_const_check: {
@@ -1391,9 +1402,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             dumpBytecodeCommentAndNewLine(location);
             break;
         }
-        case op_throw_reference_error: {
+        case op_throw_static_error: {
             int k0 = (++it)->u.operand;
-            dataLog("[%4d] throw_reference_error\t %s", location, constantName(exec, k0, getConstant(k0)).data());
+            int k1 = (++it)->u.operand;
+            dataLog("[%4d] throw_static_error\t %s, %s", location, constantName(exec, k0, getConstant(k0)).data(), k1 ? "true" : "false");
             dumpBytecodeCommentAndNewLine(location);
             break;
         }
@@ -1491,9 +1503,9 @@ void CodeBlock::dumpStatistics()
             FOR_EACH_MEMBER_VECTOR(GET_STATS)
         #undef GET_STATS
 
-        if (!codeBlock->symbolTable().isEmpty()) {
+        if (codeBlock->symbolTable() && !codeBlock->symbolTable()->isEmpty()) {
             symbolTableIsNotEmpty++;
-            symbolTableTotalSize += (codeBlock->symbolTable().capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
+            symbolTableTotalSize += (codeBlock->symbolTable()->capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
         }
 
         if (codeBlock->m_rareData) {
@@ -1561,33 +1573,26 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     , m_numCalleeRegisters(other.m_numCalleeRegisters)
     , m_numVars(other.m_numVars)
     , m_isConstructor(other.m_isConstructor)
+    , m_unlinkedCode(*other.m_globalData, other.m_ownerExecutable.get(), other.m_unlinkedCode.get())
     , m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
     , m_globalData(other.m_globalData)
     , m_instructions(other.m_instructions)
     , m_thisRegister(other.m_thisRegister)
     , m_argumentsRegister(other.m_argumentsRegister)
     , m_activationRegister(other.m_activationRegister)
-    , m_needsFullScopeChain(other.m_needsFullScopeChain)
-    , m_usesEval(other.m_usesEval)
-    , m_isNumericCompareFunction(other.m_isNumericCompareFunction)
     , m_isStrictMode(other.m_isStrictMode)
-    , m_codeType(other.m_codeType)
     , m_source(other.m_source)
     , m_sourceOffset(other.m_sourceOffset)
 #if ENABLE(VALUE_PROFILER)
     , m_executionEntryCount(0)
 #endif
-    , m_jumpTargets(other.m_jumpTargets)
-    , m_loopTargets(other.m_loopTargets)
     , m_identifiers(other.m_identifiers)
     , m_constantRegisters(other.m_constantRegisters)
     , m_functionDecls(other.m_functionDecls)
     , m_functionExprs(other.m_functionExprs)
-    , m_symbolTable(*other.m_globalData, other.m_ownerExecutable.get(), other.symbolTable())
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
-    , m_lineInfo(other.m_lineInfo)
     , m_resolveOperations(other.m_resolveOperations)
     , m_putToBaseOperations(other.m_putToBaseOperations)
 #if ENABLE(BYTECODE_COMMENTS)
@@ -1605,36 +1610,31 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
         createRareDataIfNecessary();
         
         m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
-        m_rareData->m_regexps = other.m_rareData->m_regexps;
         m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
         m_rareData->m_immediateSwitchJumpTables = other.m_rareData->m_immediateSwitchJumpTables;
         m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables;
         m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
-        m_rareData->m_expressionInfo = other.m_rareData->m_expressionInfo;
     }
 }
 
-CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, bool isConstructor, PassOwnPtr<CodeBlock> alternative)
+CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, PassOwnPtr<CodeBlock> alternative)
     : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
     , m_heap(&m_globalObject->globalData().heap)
-    , m_numCalleeRegisters(0)
-    , m_numVars(0)
-    , m_isConstructor(isConstructor)
-    , m_numParameters(0)
+    , m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters)
+    , m_numVars(unlinkedCodeBlock->m_numVars)
+    , m_isConstructor(unlinkedCodeBlock->isConstructor())
+    , m_unlinkedCode(globalObject->globalData(), ownerExecutable, unlinkedCodeBlock)
     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
-    , m_globalData(0)
-    , m_argumentsRegister(-1)
-    , m_needsFullScopeChain(ownerExecutable->needsActivation())
-    , m_usesEval(ownerExecutable->usesEval())
-    , m_isNumericCompareFunction(false)
-    , m_isStrictMode(ownerExecutable->isStrictMode())
-    , m_codeType(codeType)
+    , m_globalData(unlinkedCodeBlock->globalData())
+    , m_thisRegister(unlinkedCodeBlock->thisRegister())
+    , m_argumentsRegister(unlinkedCodeBlock->argumentsRegister())
+    , m_activationRegister(unlinkedCodeBlock->activationRegister())
+    , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
 #if ENABLE(VALUE_PROFILER)
     , m_executionEntryCount(0)
 #endif
-    , m_symbolTable(globalObject->globalData(), ownerExecutable, SharedSymbolTable::create(globalObject->globalData()))
     , m_alternative(alternative)
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
@@ -1643,7 +1643,10 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
     , m_bytecodeCommentIterator(0)
 #endif
 {
+    m_globalData->startedCompiling(this);
+
     ASSERT(m_source);
+    setNumParameters(unlinkedCodeBlock->numParameters());
 
     optimizeAfterWarmUp();
     jitAfterWarmUp();
@@ -1651,9 +1654,208 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
 #if DUMP_CODE_BLOCK_STATISTICS
     liveCodeBlockSet.add(this);
 #endif
-    // We have a stub putToBase operation to allow resolve_base to
-    // remain branchless
-    m_putToBaseOperations.append(PutToBaseOperation(isStrictMode()));
+    setIdentifiers(unlinkedCodeBlock->identifiers());
+    setConstantRegisters(unlinkedCodeBlock->constantRegisters());
+
+    m_functionDecls.grow(unlinkedCodeBlock->numberOfFunctionDecls());
+    for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
+        UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
+        unsigned lineCount = unlinkedExecutable->lineCount();
+        unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
+        unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
+        unsigned sourceLength = unlinkedExecutable->sourceLength();
+        SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine);
+        FunctionExecutable* executable = FunctionExecutable::create(*m_globalData, code, unlinkedExecutable, firstLine, firstLine + lineCount);
+        m_functionDecls[i].set(*m_globalData, ownerExecutable, executable);
+    }
+
+    m_functionExprs.grow(unlinkedCodeBlock->numberOfFunctionExprs());
+    for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
+        UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
+        unsigned lineCount = unlinkedExecutable->lineCount();
+        unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
+        unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
+        unsigned sourceLength = unlinkedExecutable->sourceLength();
+        SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine);
+        FunctionExecutable* executable = FunctionExecutable::create(*m_globalData, code, unlinkedExecutable, firstLine, firstLine + lineCount);
+        m_functionExprs[i].set(*m_globalData, ownerExecutable, executable);
+    }
+
+    if (unlinkedCodeBlock->hasRareData()) {
+        createRareDataIfNecessary();
+        if (size_t count = unlinkedCodeBlock->constantBufferCount()) {
+            m_rareData->m_constantBuffers.grow(count);
+            for (size_t i = 0; i < count; i++) {
+                const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i);
+                m_rareData->m_constantBuffers[i] = buffer;
+            }
+        }
+        if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
+            m_rareData->m_exceptionHandlers.grow(count);
+            for (size_t i = 0; i < count; i++) {
+                const UnlinkedHandlerInfo& handler = unlinkedCodeBlock->exceptionHandler(i);
+                m_rareData->m_exceptionHandlers[i].start = handler.start;
+                m_rareData->m_exceptionHandlers[i].end = handler.end;
+                m_rareData->m_exceptionHandlers[i].target = handler.target;
+                m_rareData->m_exceptionHandlers[i].scopeDepth = handler.scopeDepth + baseScopeDepth;
+#if ENABLE(JIT) && ENABLE(LLINT)
+                m_rareData->m_exceptionHandlers[i].nativeCode = CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(llint_op_catch)));
+#endif
+            }
+        }
+
+        if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) {
+            m_rareData->m_stringSwitchJumpTables.grow(count);
+            for (size_t i = 0; i < count; i++) {
+                UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin();
+                UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end();
+                for (; ptr != end; ++ptr) {
+                    OffsetLocation offset;
+                    offset.branchOffset = ptr->value;
+                    m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset);
+                }
+            }
+        }
+
+        if (size_t count = unlinkedCodeBlock->numberOfImmediateSwitchJumpTables()) {
+            m_rareData->m_immediateSwitchJumpTables.grow(count);
+            for (size_t i = 0; i < count; i++) {
+                UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->immediateSwitchJumpTable(i);
+                SimpleJumpTable& destTable = m_rareData->m_immediateSwitchJumpTables[i];
+                destTable.branchOffsets = sourceTable.branchOffsets;
+                destTable.min = sourceTable.min;
+            }
+        }
+
+        if (size_t count = unlinkedCodeBlock->numberOfCharacterSwitchJumpTables()) {
+            m_rareData->m_characterSwitchJumpTables.grow(count);
+            for (size_t i = 0; i < count; i++) {
+                UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->characterSwitchJumpTable(i);
+                SimpleJumpTable& destTable = m_rareData->m_characterSwitchJumpTables[i];
+                destTable.branchOffsets = sourceTable.branchOffsets;
+                destTable.min = sourceTable.min;
+            }
+        }
+    }
+
+    // Allocate metadata buffers for the bytecode
+#if ENABLE(LLINT)
+    if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
+        m_llintCallLinkInfos.grow(size);
+#endif
+#if ENABLE(DFG_JIT)
+    if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
+        m_arrayProfiles.grow(size);
+    if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
+        m_valueProfiles.grow(size);
+#endif
+    if (size_t size = unlinkedCodeBlock->numberOfResolveOperations())
+        m_resolveOperations.grow(size);
+    size_t putToBaseCount = unlinkedCodeBlock->numberOfPutToBaseOperations();
+    m_putToBaseOperations.reserveCapacity(putToBaseCount);
+    for (size_t i = 0; i < putToBaseCount; ++i)
+        m_putToBaseOperations.append(PutToBaseOperation(isStrictMode()));
+
+    ASSERT(m_putToBaseOperations.capacity() == putToBaseCount);
+
+    // Copy and translate the UnlinkedInstructions
+    size_t instructionCount = unlinkedCodeBlock->instructions().size();
+    UnlinkedInstruction* pc = unlinkedCodeBlock->instructions().data();
+    Vector<Instruction> instructions(instructionCount);
+    for (size_t i = 0; i < unlinkedCodeBlock->instructions().size(); ) {
+        unsigned opLength = opcodeLength(pc[i].u.opcode);
+        instructions[i] = globalData()->interpreter->getOpcode(pc[i].u.opcode);
+        for (size_t j = 1; j < opLength; ++j) {
+            if (sizeof(int32_t) != sizeof(intptr_t))
+                instructions[i + j].u.pointer = 0;
+            instructions[i + j].u.operand = pc[i + j].u.operand;
+        }
+        switch (pc[i].u.opcode) {
+#if ENABLE(DFG_JIT)
+        case op_get_by_val:
+        case op_get_argument_by_val: {
+            int arrayProfileIndex = pc[i + opLength - 2].u.operand;
+            m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+
+            instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
+            // fallthrough
+        }
+        case op_convert_this:
+        case op_resolve:
+        case op_resolve_base:
+        case op_resolve_with_base:
+        case op_resolve_with_this:
+        case op_get_by_id:
+        case op_call_put_result: {
+            ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
+            ASSERT(profile->m_bytecodeOffset == -1);
+            profile->m_bytecodeOffset = i;
+            instructions[i + opLength - 1] = profile;
+            break;
+        }
+        case op_put_by_val: {
+            int arrayProfileIndex = pc[i + opLength - 1].u.operand;
+            m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+            instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
+            break;
+        }
+
+        case op_call:
+        case op_call_eval: {
+            int arrayProfileIndex = pc[i + opLength - 1].u.operand;
+            m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+            instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
+            // fallthrough
+        }
+#endif
+#if ENABLE(LLINT)
+        case op_construct:
+            instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
+            break;
+#endif
+        case op_get_by_id_out_of_line:
+        case op_get_by_id_self:
+        case op_get_by_id_proto:
+        case op_get_by_id_chain:
+        case op_get_by_id_getter_self:
+        case op_get_by_id_getter_proto:
+        case op_get_by_id_getter_chain:
+        case op_get_by_id_custom_self:
+        case op_get_by_id_custom_proto:
+        case op_get_by_id_custom_chain:
+        case op_get_by_id_generic:
+        case op_get_array_length:
+        case op_get_string_length:
+            CRASH();
+
+        case op_init_global_const_nop: {
+            ASSERT(codeType() == GlobalCode);
+            Identifier ident = identifier(pc[i + 4].u.operand);
+            SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl());
+            if (entry.isNull())
+                break;
+
+            if (entry.couldBeWatched()) {
+                instructions[i + 0] = globalData()->interpreter->getOpcode(op_init_global_const_check);
+                instructions[i + 1] = &globalObject->registerAt(entry.getIndex());
+                instructions[i + 3] = entry.addressOfIsWatched();
+                break;
+            }
+
+            instructions[i + 0] = globalData()->interpreter->getOpcode(op_init_global_const);
+            instructions[i + 1] = &globalObject->registerAt(entry.getIndex());
+            break;
+        }
+        default:
+            break;
+        }
+        i += opLength;
+    }
+    m_instructions = WTF::RefCountedArray<Instruction>(instructions);
+
+    if (BytecodeGenerator::dumpsGeneratedCode())
+        dump(m_globalObject->globalExec());
+    m_globalData->finishedCompiling(this);
 }
 
 CodeBlock::~CodeBlock()
@@ -1704,15 +1906,6 @@ void CodeBlock::setNumParameters(int newValue)
 #endif
 }
 
-void CodeBlock::addParameter()
-{
-    m_numParameters++;
-
-#if ENABLE(VALUE_PROFILER)
-    m_argumentValueProfiles.append(ValueProfile());
-#endif
-}
-
 void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC)
 {
     Interpreter* interpreter = m_globalData->interpreter;
@@ -1795,6 +1988,8 @@ void CodeBlock::visitAggregate(SlotVisitor& visitor)
     if (!!m_alternative)
         m_alternative->visitAggregate(visitor);
 
+    visitor.append(&m_unlinkedCode);
+
     // There are three things that may use unconditional finalizers: lazy bytecode freeing,
     // inline cache clearing, and jettisoning. The probability of us wanting to do at
     // least one of those things is probably quite close to 1. So we add one no matter what
@@ -1909,8 +2104,9 @@ void CodeBlock::finalizeUnconditionally()
 #if ENABLE(LLINT)
     Interpreter* interpreter = m_globalData->interpreter;
     if (!!numberOfInstructions()) {
-        for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
-            Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]];
+        const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
+        for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
+            Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
             switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
             case op_get_by_id:
             case op_get_by_id_out_of_line:
@@ -2062,14 +2258,9 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
 {
     visitor.append(&m_globalObject);
     visitor.append(&m_ownerExecutable);
-    visitor.append(&m_symbolTable);
-    if (m_rareData) {
+    visitor.append(&m_unlinkedCode);
+    if (m_rareData)
         m_rareData->m_evalCodeCache.visitAggregate(visitor);
-        size_t regExpCount = m_rareData->m_regexps.size();
-        WriteBarrier<RegExp>* regexps = m_rareData->m_regexps.data();
-        for (size_t i = 0; i < regExpCount; i++)
-            visitor.append(regexps + i);
-    }
     visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
     for (size_t i = 0; i < m_functionExprs.size(); ++i)
         visitor.append(&m_functionExprs[i]);
@@ -2196,64 +2387,17 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 {
     ASSERT(bytecodeOffset < instructions().size());
-
-    Vector<LineInfo>& lineInfo = m_lineInfo;
-
-    int low = 0;
-    int high = lineInfo.size();
-    while (low < high) {
-        int mid = low + (high - low) / 2;
-        if (lineInfo[mid].instructionOffset <= bytecodeOffset)
-            low = mid + 1;
-        else
-            high = mid;
-    }
-
-    if (!low)
-        return m_ownerExecutable->source().firstLine();
-    return lineInfo[low - 1].lineNumber;
+    return m_ownerExecutable->lineNo() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset);
 }
 
 void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
 {
-    ASSERT(bytecodeOffset < instructions().size());
-
-    if (!m_rareData) {
-        startOffset = 0;
-        endOffset = 0;
-        divot = 0;
-        return;
-    }
-
-    Vector<ExpressionRangeInfo>& expressionInfo = m_rareData->m_expressionInfo;
-
-    int low = 0;
-    int high = expressionInfo.size();
-    while (low < high) {
-        int mid = low + (high - low) / 2;
-        if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
-            low = mid + 1;
-        else
-            high = mid;
-    }
-
-    ASSERT(low);
-    if (!low) {
-        startOffset = 0;
-        endOffset = 0;
-        divot = 0;
-        return;
-    }
-
-    startOffset = expressionInfo[low - 1].startOffset;
-    endOffset = expressionInfo[low - 1].endOffset;
-    divot = expressionInfo[low - 1].divotPoint + m_sourceOffset;
-    return;
+    m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset);
+    divot += m_sourceOffset;
 }
 
 void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
 {
-    m_propertyAccessInstructions.shrinkToFit();
 #if ENABLE(LLINT)
     m_llintCallLinkInfos.shrinkToFit();
 #endif
@@ -2264,7 +2408,6 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
 #if ENABLE(VALUE_PROFILER)
     if (shrinkMode == EarlyShrink)
         m_argumentValueProfiles.shrinkToFit();
-    m_valueProfiles.shrinkToFit();
     m_rareCaseProfiles.shrinkToFit();
     m_specialFastCaseProfiles.shrinkToFit();
 #endif
@@ -2276,15 +2419,11 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
         m_constantRegisters.shrinkToFit();
     } // else don't shrink these, because we would have already pointed pointers into these tables.
 
-    m_resolveOperations.shrinkToFit();
-    m_lineInfo.shrinkToFit();
     if (m_rareData) {
         m_rareData->m_exceptionHandlers.shrinkToFit();
-        m_rareData->m_regexps.shrinkToFit();
         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
-        m_rareData->m_expressionInfo.shrinkToFit();
 #if ENABLE(JIT)
         m_rareData->m_callReturnIndexVector.shrinkToFit();
 #endif
@@ -2312,7 +2451,7 @@ void CodeBlock::createActivation(CallFrame* callFrame)
     ASSERT(codeType() == FunctionCode);
     ASSERT(needsFullScopeChain());
     ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
-    JSActivation* activation = JSActivation::create(callFrame->globalData(), callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
+    JSActivation* activation = JSActivation::create(callFrame->globalData(), callFrame, this);
     callFrame->uncheckedR(activationRegister()) = JSValue(activation);
     callFrame->setScope(activation);
 }
index fa74a7dcfb1cefffbab0f4d9523bee78bcda8dec..a28064940aecd69c81b1d91239109dbc6f9833c9 100644 (file)
@@ -120,7 +120,7 @@ namespace JSC {
     protected:
         CodeBlock(CopyParsedBlockTag, CodeBlock& other);
         
-        CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, bool isConstructor, PassOwnPtr<CodeBlock> alternative);
+        CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSGlobalObject*, unsigned baseScopeDepth, PassRefPtr<SourceProvider>, unsigned sourceOffset, PassOwnPtr<CodeBlock> alternative);
 
         WriteBarrier<JSGlobalObject> m_globalObject;
         Heap* m_heap;
@@ -130,7 +130,6 @@ namespace JSC {
         
         int numParameters() const { return m_numParameters; }
         void setNumParameters(int newValue);
-        void addParameter();
         
         int* addressOfNumParameters() { return &m_numParameters; }
         static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
@@ -434,8 +433,7 @@ namespace JSC {
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
 
-        void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
-        bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
+        bool isNumericCompareFunction() { return m_unlinkedCode->isNumericCompareFunction(); }
 
         unsigned numberOfInstructions() const { return m_instructions.size(); }
         RefCountedArray<Instruction>& instructions() { return m_instructions; }
@@ -524,10 +522,8 @@ namespace JSC {
         void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
         int thisRegister() const { return m_thisRegister; }
 
-        void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
-        bool needsFullScopeChain() const { return m_needsFullScopeChain; }
-        void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
-        bool usesEval() const { return m_usesEval; }
+        bool needsFullScopeChain() const { return m_unlinkedCode->needsFullScopeChain(); }
+        bool usesEval() const { return m_unlinkedCode->usesEval(); }
         
         void setArgumentsRegister(int argumentsRegister)
         {
@@ -589,37 +585,28 @@ namespace JSC {
             if (usesArguments() && operand == unmodifiedArgumentsRegister(argumentsRegister()))
                 return true;
 
+            // We're in global code so there are no locals to capture
+            if (!symbolTable())
+                return false;
+
             return operand >= symbolTable()->captureStart()
                 && operand < symbolTable()->captureEnd();
         }
 
-        CodeType codeType() const { return m_codeType; }
+        CodeType codeType() const { return m_unlinkedCode->codeType(); }
 
         SourceProvider* source() const { return m_source.get(); }
         unsigned sourceOffset() const { return m_sourceOffset; }
 
-        size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
-        void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
-        unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
-        unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
+        size_t numberOfJumpTargets() const { return m_unlinkedCode->numberOfJumpTargets(); }
+        unsigned jumpTarget(int index) const { return m_unlinkedCode->jumpTarget(index); }
 
         void createActivation(CallFrame*);
 
         void clearEvalCache();
         
         String nameForRegister(int registerNumber);
-        
-        void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
-        {
-            m_propertyAccessInstructions.append(propertyAccessInstruction);
-        }
-#if ENABLE(LLINT)
-        LLIntCallLinkInfo* addLLIntCallLinkInfo()
-        {
-            m_llintCallLinkInfos.append(LLIntCallLinkInfo());
-            return &m_llintCallLinkInfos.last();
-        }
-#endif
+
 #if ENABLE(JIT)
         void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
         size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
@@ -647,14 +634,7 @@ namespace JSC {
             ASSERT(result->m_bytecodeOffset == -1);
             return result;
         }
-        
-        ValueProfile* addValueProfile(int bytecodeOffset)
-        {
-            ASSERT(bytecodeOffset != -1);
-            ASSERT(m_valueProfiles.isEmpty() || m_valueProfiles.last().m_bytecodeOffset < bytecodeOffset);
-            m_valueProfiles.append(ValueProfile(bytecodeOffset));
-            return &m_valueProfiles.last();
-        }
+
         unsigned numberOfValueProfiles() { return m_valueProfiles.size(); }
         ValueProfile* valueProfile(int index)
         {
@@ -780,25 +760,24 @@ namespace JSC {
         // Exception handling support
 
         size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
-        void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
-        HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
-
-        void addExpressionInfo(const ExpressionRangeInfo& expressionInfo)
+        void allocateHandlers(const Vector<UnlinkedHandlerInfo>& unlinkedHandlers)
         {
+            size_t count = unlinkedHandlers.size();
+            if (!count)
+                return;
             createRareDataIfNecessary();
-            m_rareData->m_expressionInfo.append(expressionInfo);
-        }
-
-        void addLineInfo(unsigned bytecodeOffset, int lineNo)
-        {
-            Vector<LineInfo>& lineInfo = m_lineInfo;
-            if (!lineInfo.size() || lineInfo.last().lineNumber != lineNo) {
-                LineInfo info = { bytecodeOffset, lineNo };
-                lineInfo.append(info);
+            m_rareData->m_exceptionHandlers.resize(count);
+            for (size_t i = 0; i < count; ++i) {
+                m_rareData->m_exceptionHandlers[i].start = unlinkedHandlers[i].start;
+                m_rareData->m_exceptionHandlers[i].end = unlinkedHandlers[i].end;
+                m_rareData->m_exceptionHandlers[i].target = unlinkedHandlers[i].target;
+                m_rareData->m_exceptionHandlers[i].scopeDepth = unlinkedHandlers[i].scopeDepth;
             }
+
         }
+        HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
 
-        bool hasExpressionInfo() { return m_rareData && m_rareData->m_expressionInfo.size(); }
+        bool hasExpressionInfo() { return m_unlinkedCode->hasExpressionInfo(); }
 
 #if ENABLE(JIT)
         Vector<CallReturnOffsetToBytecodeOffset>& callReturnIndexVector()
@@ -873,6 +852,8 @@ namespace JSC {
             m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v);
             return result;
         }
+
+
         unsigned addOrFindConstant(JSValue);
         WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
         ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
@@ -896,20 +877,7 @@ namespace JSC {
         }
         FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
 
-        unsigned addRegExp(RegExp* r)
-        {
-            createRareDataIfNecessary();
-            unsigned size = m_rareData->m_regexps.size();
-            m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_globalData, ownerExecutable(), r));
-            return size;
-        }
-        unsigned numberOfRegExps() const
-        {
-            if (!m_rareData)
-                return 0;
-            return m_rareData->m_regexps.size();
-        }
-        RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
+        RegExp* regexp(int index) const { return m_unlinkedCode->regexp(index); }
 
         unsigned numberOfConstantBuffers() const
         {
@@ -924,10 +892,6 @@ namespace JSC {
             m_rareData->m_constantBuffers.append(buffer);
             return size;
         }
-        unsigned addConstantBuffer(unsigned length)
-        {
-            return addConstantBuffer(Vector<JSValue>(length));
-        }
 
         Vector<JSValue>& constantBufferAsVector(unsigned index)
         {
@@ -964,7 +928,7 @@ namespace JSC {
         StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
 
 
-        SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
+        SharedSymbolTable* symbolTable() const { return m_unlinkedCode->symbolTable(); }
 
         EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
 
@@ -1208,6 +1172,8 @@ namespace JSC {
         virtual void visitWeakReferences(SlotVisitor&);
         virtual void finalizeUnconditionally();
 
+        UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }
+
     private:
         friend class DFGCodeBlocks;
         
@@ -1219,7 +1185,21 @@ namespace JSC {
 #if ENABLE(VALUE_PROFILER)
         void updateAllPredictionsAndCountLiveness(OperationInProgress, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
 #endif
-        
+
+        void setIdentifiers(const Vector<Identifier>& identifiers)
+        {
+            ASSERT(m_identifiers.isEmpty());
+            m_identifiers.appendVector(identifiers);
+        }
+
+        void setConstantRegisters(const Vector<WriteBarrier<Unknown> >& constants)
+        {
+            size_t count = constants.size();
+            m_constantRegisters.resize(count);
+            for (size_t i = 0; i < count; i++)
+                m_constantRegisters[i].set(*m_globalData, ownerExecutable(), constants[i].get());
+        }
+
         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&);
 
         CString registerName(ExecState*, int r) const;
@@ -1269,29 +1249,21 @@ namespace JSC {
 #if ENABLE(JIT)
         void resetStubInternal(RepatchBuffer&, StructureStubInfo&);
 #endif
-        
+        WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode;
         int m_numParameters;
-
         WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
         RefCountedArray<Instruction> m_instructions;
-
         int m_thisRegister;
         int m_argumentsRegister;
         int m_activationRegister;
 
-        bool m_needsFullScopeChain;
-        bool m_usesEval;
-        bool m_isNumericCompareFunction;
         bool m_isStrictMode;
 
-        CodeType m_codeType;
-
         RefPtr<SourceProvider> m_source;
         unsigned m_sourceOffset;
 
-        Vector<unsigned> m_propertyAccessInstructions;
 #if ENABLE(LLINT)
         SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos;
         SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls;
@@ -1362,18 +1334,15 @@ namespace JSC {
         unsigned m_executionEntryCount;
 #endif
 
-        Vector<unsigned> m_jumpTargets;
-        Vector<unsigned> m_loopTargets;
-
         // Constant Pool
         Vector<Identifier> m_identifiers;
         COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown);
+        // TODO: This could just be a pointer to m_unlinkedCodeBlock's data, but the DFG mutates
+        // it, so we're stuck with it for now.
         Vector<WriteBarrier<Unknown> > m_constantRegisters;
         Vector<WriteBarrier<FunctionExecutable> > m_functionDecls;
         Vector<WriteBarrier<FunctionExecutable> > m_functionExprs;
 
-        WriteBarrier<SharedSymbolTable> m_symbolTable;
-
         OwnPtr<CodeBlock> m_alternative;
         
         ExecutionCounter m_llintExecuteCounter;
@@ -1384,11 +1353,6 @@ namespace JSC {
         uint16_t m_optimizationDelayCounter;
         uint16_t m_reoptimizationRetryCounter;
 
-        Vector<LineInfo> m_lineInfo;
-#if ENABLE(BYTECODE_COMMENTS)
-        Vector<Comment>  m_bytecodeComments;
-        size_t m_bytecodeCommentIterator;
-#endif
         Vector<ResolveOperations> m_resolveOperations;
         Vector<PutToBaseOperation, 1> m_putToBaseOperations;
 
@@ -1397,9 +1361,6 @@ namespace JSC {
         public:
             Vector<HandlerInfo> m_exceptionHandlers;
 
-            // Rare Constants
-            Vector<WriteBarrier<RegExp> > m_regexps;
-
             // Buffers used for large array literals
             Vector<Vector<JSValue> > m_constantBuffers;
             
@@ -1410,9 +1371,6 @@ namespace JSC {
 
             EvalCodeCache m_evalCodeCache;
 
-            // Expression info - present if debugging.
-            Vector<ExpressionRangeInfo> m_expressionInfo;
-            // Line info - present if profiling or debugging.
 #if ENABLE(JIT)
             Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
 #endif
@@ -1440,8 +1398,8 @@ namespace JSC {
         {
         }
         
-        GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, PassOwnPtr<CodeBlock> alternative)
-            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, false, alternative)
+        GlobalCodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, PassOwnPtr<CodeBlock> alternative)
+            : CodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, baseScopeDepth, sourceProvider, sourceOffset, alternative)
         {
         }
     };
@@ -1453,11 +1411,11 @@ namespace JSC {
         {
         }
 
-        ProgramCodeBlock(ProgramExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, PassOwnPtr<CodeBlock> alternative)
-            : GlobalCodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, 0, alternative)
+        ProgramCodeBlock(ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, PassOwnPtr<CodeBlock> alternative)
+            : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, 0, sourceProvider, 0, alternative)
         {
         }
-        
+
 #if ENABLE(JIT)
     protected:
         virtual JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
@@ -1472,26 +1430,16 @@ namespace JSC {
     public:
         EvalCodeBlock(CopyParsedBlockTag, EvalCodeBlock& other)
             : GlobalCodeBlock(CopyParsedBlock, other)
-            , m_baseScopeDepth(other.m_baseScopeDepth)
-            , m_variables(other.m_variables)
         {
         }
         
-        EvalCodeBlock(EvalExecutable* ownerExecutable, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth, PassOwnPtr<CodeBlock> alternative)
-            : GlobalCodeBlock(ownerExecutable, EvalCode, globalObject, sourceProvider, 0, alternative)
-            , m_baseScopeDepth(baseScopeDepth)
+        EvalCodeBlock(EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth, PassOwnPtr<CodeBlock> alternative)
+            : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, baseScopeDepth, sourceProvider, 0, alternative)
         {
         }
 
-        int baseScopeDepth() const { return m_baseScopeDepth; }
-
-        const Identifier& variable(unsigned index) { return m_variables[index]; }
-        unsigned numVariables() { return m_variables.size(); }
-        void adoptVariables(Vector<Identifier>& variables)
-        {
-            ASSERT(m_variables.isEmpty());
-            m_variables.swap(variables);
-        }
+        const Identifier& variable(unsigned index) { return unlinkedEvalCodeBlock()->variable(index); }
+        unsigned numVariables() { return unlinkedEvalCodeBlock()->numVariables(); }
         
 #if ENABLE(JIT)
     protected:
@@ -1503,8 +1451,7 @@ namespace JSC {
 #endif
 
     private:
-        int m_baseScopeDepth;
-        Vector<Identifier> m_variables;
+        UnlinkedEvalCodeBlock* unlinkedEvalCodeBlock() const { return jsCast<UnlinkedEvalCodeBlock*>(unlinkedCodeBlock()); }
     };
 
     class FunctionCodeBlock : public CodeBlock {
@@ -1514,8 +1461,8 @@ namespace JSC {
         {
         }
 
-        FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, bool isConstructor, PassOwnPtr<CodeBlock> alternative = nullptr)
-            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, isConstructor, alternative)
+        FunctionCodeBlock(FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, PassOwnPtr<CodeBlock> alternative = nullptr)
+            : CodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, 0, sourceProvider, sourceOffset, alternative)
         {
         }
         
index 17b9c6782ec3fe5c97c0de31be3aa563d173f1d1..8979d0b7b2d9549e28b0d6b6a17192714d78bd61 100644 (file)
@@ -118,7 +118,8 @@ namespace JSC {
         macro(op_put_to_base, 5) \
         macro(op_put_to_base_variable, 5) \
         \
-        macro(op_init_global_const, 3) \
+        macro(op_init_global_const_nop, 5) \
+        macro(op_init_global_const, 5) \
         macro(op_init_global_const_check, 5) \
         macro(op_get_by_id, 9) /* has value profiling */ \
         macro(op_get_by_id_out_of_line, 9) /* has value profiling */ \
@@ -204,7 +205,7 @@ namespace JSC {
         \
         macro(op_catch, 2) \
         macro(op_throw, 2) \
-        macro(op_throw_reference_error, 2) \
+        macro(op_throw_static_error, 3) \
         \
         macro(op_debug, 5) \
         macro(op_profile_will_call, 2) \
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
new file mode 100644 (file)
index 0000000..8aa4840
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 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 "UnlinkedCodeBlock.h"
+
+#include "BytecodeGenerator.h"
+#include "ClassInfo.h"
+#include "CodeCache.h"
+#include "Executable.h"
+#include "JSString.h"
+#include "SourceProvider.h"
+#include "Structure.h"
+#include "SymbolTable.h"
+
+namespace JSC {
+
+const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) };
+const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
+const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) };
+const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) };
+const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
+const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
+
+unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v)
+{
+    unsigned numberOfConstants = numberOfConstantRegisters();
+    for (unsigned i = 0; i < numberOfConstants; ++i) {
+        if (getConstant(FirstConstantRegisterIndex + i) == v)
+            return i;
+    }
+    return addConstant(v);
+}
+
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(JSGlobalData* globalData, Structure* structure, const SourceCode& source, FunctionBodyNode* node)
+    : Base(*globalData, structure)
+    , m_numCapturedVariables(node->capturedVariableCount())
+    , m_forceUsesArguments(node->usesArguments())
+    , m_isInStrictContext(node->isStrictMode())
+    , m_hasCapturedVariables(node->hasCapturedVariables())
+    , m_name(node->ident())
+    , m_inferredName(node->inferredName())
+    , m_parameters(node->parameters())
+    , m_firstLineOffset(node->firstLine() - source.firstLine())
+    , m_lineCount(node->lastLine() - node->firstLine())
+    , m_startOffset(node->source().startOffset() - source.startOffset())
+    , m_sourceLength(node->source().length())
+    , m_features(node->features())
+    , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle())
+{
+}
+
+void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_codeBlockForCall);
+    visitor.append(&thisObject->m_codeBlockForConstruct);
+    visitor.append(&thisObject->m_nameValue);
+    visitor.append(&thisObject->m_symbolTableForCall);
+    visitor.append(&thisObject->m_symbolTableForConstruct);
+}
+
+FunctionExecutable* UnlinkedFunctionExecutable::link(JSGlobalData& globalData, const SourceCode& source, size_t lineOffset, size_t sourceOffset)
+{
+    unsigned firstLine = lineOffset + m_firstLineOffset;
+    unsigned startOffset = sourceOffset + m_startOffset;
+    SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine);
+    return FunctionExecutable::create(globalData, code, this, firstLine, firstLine + m_lineCount);
+}
+
+UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception)
+{
+    ParserError error;
+    CodeCache* codeCache = exec->globalData().codeCache();
+    UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(exec->globalData(), name, source, error);
+    if (error.m_type != ParserError::ErrorNone) {
+        *exception = error.toErrorObject(exec->lexicalGlobalObject(), source);
+        return 0;
+    }
+
+    return executable;
+}
+
+UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(JSGlobalData& globalData, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+    switch (specializationKind) {
+    case CodeForCall:
+        if (m_codeBlockForCall)
+            return m_codeBlockForCall.get();
+        break;
+    case CodeForConstruct:
+        if (m_codeBlockForConstruct)
+            return m_codeBlockForConstruct.get();
+        break;
+    }
+
+    UnlinkedFunctionCodeBlock* result = globalData.codeCache()->getFunctionCodeBlock(globalData, this, source, specializationKind, debuggerMode, profilerMode, error);
+    
+    if (error.m_type != ParserError::ErrorNone)
+        return 0;
+
+    switch (specializationKind) {
+    case CodeForCall:
+        m_codeBlockForCall.set(globalData, this, result);
+        m_symbolTableForCall.set(globalData, this, result->symbolTable());
+        break;
+    case CodeForConstruct:
+        m_codeBlockForConstruct.set(globalData, this, result);
+        m_symbolTableForConstruct.set(globalData, this, result->symbolTable());
+        break;
+    }
+    return result;
+}
+
+String UnlinkedFunctionExecutable::paramString() const
+{
+    FunctionParameters& parameters = *m_parameters;
+    StringBuilder builder;
+    for (size_t pos = 0; pos < parameters.size(); ++pos) {
+        if (!builder.isEmpty())
+            builder.appendLiteral(", ");
+        builder.append(parameters[pos].string());
+    }
+    return builder.toString();
+}
+
+UnlinkedCodeBlock::UnlinkedCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
+    : Base(*globalData, structure)
+    , m_numVars(0)
+    , m_numCalleeRegisters(0)
+    , m_numParameters(0)
+    , m_globalData(globalData)
+    , m_argumentsRegister(-1)
+    , m_needsFullScopeChain(info.m_needsActivation)
+    , m_usesEval(info.m_usesEval)
+    , m_isNumericCompareFunction(false)
+    , m_isStrictMode(info.m_isStrictMode)
+    , m_isConstructor(info.m_isConstructor)
+    , m_hasCapturedVariables(false)
+    , m_firstLine(0)
+    , m_lineCount(0)
+    , m_features(0)
+    , m_codeType(codeType)
+    , m_resolveOperationCount(0)
+    , m_putToBaseOperationCount(1)
+    , m_arrayProfileCount(0)
+    , m_valueProfileCount(0)
+    , m_llintCallLinkInfoCount(0)
+#if ENABLE(BYTECODE_COMMENTS)
+    , m_bytecodeCommentIterator(0)
+#endif
+{
+
+}
+
+void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_symbolTable);
+    for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
+        visitor.append(ptr);
+    for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)
+        visitor.append(ptr);
+    visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
+    if (thisObject->m_rareData) {
+        for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
+            visitor.append(&thisObject->m_rareData->m_regexps[i]);
+    }
+}
+
+int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
+{
+    ASSERT(bytecodeOffset < instructions().size());
+    Vector<LineInfo>& lineInfo = m_lineInfo;
+    
+    int low = 0;
+    int high = lineInfo.size();
+    while (low < high) {
+        int mid = low + (high - low) / 2;
+        if (lineInfo[mid].instructionOffset <= bytecodeOffset)
+            low = mid + 1;
+        else
+            high = mid;
+    }
+    
+    if (!low)
+        return 0;
+    return lineInfo[low - 1].lineNumber;
+}
+
+void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
+{
+    ASSERT(bytecodeOffset < instructions().size());
+
+    if (!m_expressionInfo.size()) {
+        startOffset = 0;
+        endOffset = 0;
+        divot = 0;
+        return;
+    }
+
+    Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
+
+    int low = 0;
+    int high = expressionInfo.size();
+    while (low < high) {
+        int mid = low + (high - low) / 2;
+        if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
+            low = mid + 1;
+        else
+            high = mid;
+    }
+
+    ASSERT(low);
+    if (!low) {
+        startOffset = 0;
+        endOffset = 0;
+        divot = 0;
+        return;
+    }
+
+    startOffset = expressionInfo[low - 1].startOffset;
+    endOffset = expressionInfo[low - 1].endOffset;
+    divot = expressionInfo[low - 1].divotPoint;
+}
+
+void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
+    for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
+        visitor.append(&thisObject->m_functionDeclarations[i].second);
+}
+
+UnlinkedCodeBlock::~UnlinkedCodeBlock()
+{
+}
+
+void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
+{
+    jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
+}
+
+void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
+{
+    jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
+}
+
+void UnlinkedFunctionCodeBlock::destroy(JSCell* cell)
+{
+    jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock();
+}
+
+void UnlinkedFunctionExecutable::destroy(JSCell* cell)
+{
+    jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
+}
+
+}
+
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
new file mode 100644 (file)
index 0000000..bf3f5fd
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2012 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 UnlinkedCodeBlock_h
+#define UnlinkedCodeBlock_h
+
+#include "BytecodeConventions.h"
+#include "CodeSpecializationKind.h"
+#include "CodeType.h"
+#include "ExpressionRangeInfo.h"
+#include "Identifier.h"
+#include "JSCell.h"
+#include "LineInfo.h"
+#include "Nodes.h"
+#include "RegExp.h"
+#include "SpecialPointer.h"
+
+#include <wtf/RefCountedArray.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class Debugger;
+class FunctionBodyNode;
+class FunctionExecutable;
+class FunctionParameters;
+struct ParserError;
+class ScriptExecutable;
+class SourceCode;
+class SourceProvider;
+class SharedSymbolTable;
+class UnlinkedCodeBlock;
+class UnlinkedFunctionCodeBlock;
+
+typedef unsigned UnlinkedValueProfile;
+typedef unsigned UnlinkedArrayProfile;
+typedef unsigned UnlinkedLLIntCallLinkInfo;
+
+struct ExecutableInfo {
+    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor)
+        : m_needsActivation(needsActivation)
+        , m_usesEval(usesEval)
+        , m_isStrictMode(isStrictMode)
+        , m_isConstructor(isConstructor)
+    {
+    }
+    bool m_needsActivation;
+    bool m_usesEval;
+    bool m_isStrictMode;
+    bool m_isConstructor;
+};
+
+class UnlinkedFunctionExecutable : public JSCell {
+public:
+    friend class CodeCache;
+    typedef JSCell Base;
+    static UnlinkedFunctionExecutable* create(JSGlobalData* globalData, const SourceCode& source, FunctionBodyNode* node)
+    {
+        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(globalData->heap)) UnlinkedFunctionExecutable(globalData, globalData->unlinkedFunctionExecutableStructure.get(), source, node);
+        instance->finishCreation(*globalData);
+        return instance;
+    }
+
+    const Identifier& name() const { return m_name; }
+    const Identifier& inferredName() const { return m_inferredName; }
+    JSString* nameValue() const { return m_nameValue.get(); }
+    SharedSymbolTable* symbolTable(CodeSpecializationKind kind)
+    {
+        return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get();
+    }
+    size_t parameterCount() const { return m_parameters->size(); }
+    bool isInStrictContext() const { return m_isInStrictContext; }
+    FunctionNameIsInScopeToggle functionNameIsInScopeToggle() const { return m_functionNameIsInScopeToggle; }
+
+    unsigned firstLineOffset() const { return m_firstLineOffset; }
+    unsigned lineCount() const { return m_lineCount; }
+    unsigned startOffset() const { return m_startOffset; }
+    unsigned sourceLength() { return m_sourceLength; }
+
+    String paramString() const;
+
+    UnlinkedFunctionCodeBlock* codeBlockFor(JSGlobalData&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+
+    static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+
+    FunctionExecutable* link(JSGlobalData&, const SourceCode&, size_t lineOffset, size_t sourceOffset);
+
+    void clearCode()
+    {
+        m_symbolTableForCall.clear();
+        m_symbolTableForConstruct.clear();
+        m_codeBlockForCall.clear();
+        m_codeBlockForConstruct.clear();
+    }
+
+    FunctionParameters* parameters() { return m_parameters.get(); }
+
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+    {
+        m_features = features;
+        m_hasCapturedVariables = hasCapturedVariables;
+        m_lineCount = lastLine - firstLine;
+    }
+
+    bool forceUsesArguments() const { return m_forceUsesArguments; }
+
+    CodeFeatures features() const { return m_features; }
+    bool hasCapturedVariables() const { return m_hasCapturedVariables; }
+
+    static const bool needsDestruction = true;
+    static const bool hasImmortalStructure = true;
+    static void destroy(JSCell*);
+
+private:
+    UnlinkedFunctionExecutable(JSGlobalData*, Structure*, const SourceCode&, FunctionBodyNode*);
+    WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
+    WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
+
+    unsigned m_numCapturedVariables : 29;
+    bool m_forceUsesArguments : 1;
+    bool m_isInStrictContext : 1;
+    bool m_hasCapturedVariables : 1;
+
+    Identifier m_name;
+    Identifier m_inferredName;
+    WriteBarrier<JSString> m_nameValue;
+    WriteBarrier<SharedSymbolTable> m_symbolTableForCall;
+    WriteBarrier<SharedSymbolTable> m_symbolTableForConstruct;
+    RefPtr<FunctionParameters> m_parameters;
+    unsigned m_firstLineOffset;
+    unsigned m_lineCount;
+    unsigned m_startOffset;
+    unsigned m_sourceLength;
+
+    CodeFeatures m_features;
+
+    FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
+
+protected:
+    void finishCreation(JSGlobalData& globalData)
+    {
+        Base::finishCreation(globalData);
+        m_nameValue.set(globalData, this, jsString(&globalData, name().string()));
+    }
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+public:
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+struct UnlinkedStringJumpTable {
+    typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
+    StringOffsetTable offsetTable;
+
+    inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
+    {
+        StringOffsetTable::const_iterator end = offsetTable.end();
+        StringOffsetTable::const_iterator loc = offsetTable.find(value);
+        if (loc == end)
+            return defaultOffset;
+        return loc->value;
+    }
+
+};
+
+struct UnlinkedSimpleJumpTable {
+    Vector<int32_t> branchOffsets;
+    int32_t min;
+
+    int32_t offsetForValue(int32_t value, int32_t defaultOffset);
+    void add(int32_t key, int32_t offset)
+    {
+        if (!branchOffsets[key])
+            branchOffsets[key] = offset;
+    }
+};
+
+struct UnlinkedHandlerInfo {
+    uint32_t start;
+    uint32_t end;
+    uint32_t target;
+    uint32_t scopeDepth;
+};
+
+struct UnlinkedInstruction {
+    UnlinkedInstruction() { u.operand = 0; }
+    UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
+    UnlinkedInstruction(int operand) { u.operand = operand; }
+    union {
+        OpcodeID opcode;
+        int32_t operand;
+    } u;
+};
+
+class UnlinkedCodeBlock : public JSCell {
+public:
+    typedef JSCell Base;
+    static const bool needsDestruction = true;
+    static const bool hasImmortalStructure = true;
+
+    enum { CallFunction, ApplyFunction };
+
+    bool isConstructor() const { return m_isConstructor; }
+    bool isStrictMode() const { return m_isStrictMode; }
+    bool usesEval() const { return m_usesEval; }
+
+    bool needsFullScopeChain() const { return m_needsFullScopeChain; }
+    void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
+
+    void addExpressionInfo(const ExpressionRangeInfo& expressionInfo)
+    {
+        m_expressionInfo.append(expressionInfo);
+    }
+
+    void addLineInfo(unsigned bytecodeOffset, int lineNo)
+    {
+        Vector<LineInfo>& lineInfo = m_lineInfo;
+        if (!lineInfo.size() || lineInfo.last().lineNumber != lineNo) {
+            LineInfo info = { bytecodeOffset, lineNo };
+            lineInfo.append(info);
+        }
+    }
+
+    bool hasExpressionInfo() { return m_expressionInfo.size(); }
+
+    // Special registers
+    void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
+    void setActivationRegister(int activationRegister) { m_activationRegister = activationRegister; }
+
+    void setArgumentsRegister(int argumentsRegister) { m_argumentsRegister = argumentsRegister; }
+    bool usesArguments() const { return m_argumentsRegister != -1; }
+    int argumentsRegister() const { return m_argumentsRegister; }
+
+    // Parameter information
+    void setNumParameters(int newValue) { m_numParameters = newValue; }
+    void addParameter() { m_numParameters++; }
+    unsigned numParameters() const { return m_numParameters; }
+
+    unsigned addRegExp(RegExp* r)
+    {
+        createRareDataIfNecessary();
+        unsigned size = m_rareData->m_regexps.size();
+        m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_globalData, this, r));
+        return size;
+    }
+    unsigned numberOfRegExps() const
+    {
+        if (!m_rareData)
+            return 0;
+        return m_rareData->m_regexps.size();
+    }
+    RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
+
+    // Constant Pools
+
+    size_t numberOfIdentifiers() const { return m_identifiers.size(); }
+    void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
+    const Identifier& identifier(int index) const { return m_identifiers[index]; }
+    const Vector<Identifier>& identifiers() const { return m_identifiers; }
+
+    size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
+    unsigned addConstant(JSValue v)
+    {
+        unsigned result = m_constantRegisters.size();
+        m_constantRegisters.append(WriteBarrier<Unknown>());
+        m_constantRegisters.last().set(*m_globalData, this, v);
+        return result;
+    }
+    unsigned addOrFindConstant(JSValue);
+    const Vector<WriteBarrier<Unknown> >& constantRegisters() { return m_constantRegisters; }
+    const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
+    ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
+    ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
+
+    // Jumps
+    size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
+    void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
+    unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
+    unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
+
+    void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
+    bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
+
+    void shrinkToFit()
+    {
+        m_jumpTargets.shrinkToFit();
+        m_identifiers.shrinkToFit();
+        m_constantRegisters.shrinkToFit();
+        m_functionDecls.shrinkToFit();
+        m_functionExprs.shrinkToFit();
+        m_lineInfo.shrinkToFit();
+        m_propertyAccessInstructions.shrinkToFit();
+        m_expressionInfo.shrinkToFit();
+
+#if ENABLE(BYTECODE_COMMENTS)
+        m_bytecodeComments.shrinkToFit();
+#endif
+        if (m_rareData) {
+            m_rareData->m_exceptionHandlers.shrinkToFit();
+            m_rareData->m_regexps.shrinkToFit();
+            m_rareData->m_constantBuffers.shrinkToFit();
+            m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
+            m_rareData->m_characterSwitchJumpTables.shrinkToFit();
+            m_rareData->m_stringSwitchJumpTables.shrinkToFit();
+        }
+    }
+
+    unsigned numberOfInstructions() const { return m_unlinkedInstructions.size(); }
+    RefCountedArray<UnlinkedInstruction>& instructions() { return m_unlinkedInstructions; }
+    const RefCountedArray<UnlinkedInstruction>& instructions() const { return m_unlinkedInstructions; }
+
+    int m_numVars;
+    int m_numCapturedVars;
+    int m_numCalleeRegisters;
+
+    // Jump Tables
+
+    size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
+    UnlinkedSimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
+    UnlinkedSimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
+
+    size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
+    UnlinkedSimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
+    UnlinkedSimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
+
+    size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
+    UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
+    UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
+
+    unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
+    {
+        unsigned size = m_functionDecls.size();
+        m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
+        m_functionDecls.last().set(*m_globalData, this, n);
+        return size;
+    }
+    UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
+    size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
+    unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
+    {
+        unsigned size = m_functionExprs.size();
+        m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
+        m_functionExprs.last().set(*m_globalData, this, n);
+        return size;
+    }
+    UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
+    size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
+
+    // Exception handling support
+    size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
+    void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
+    UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
+
+    SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
+
+    JSGlobalData* globalData() const { return m_globalData; }
+
+    unsigned addResolve() { return m_resolveOperationCount++; }
+    unsigned numberOfResolveOperations() const { return m_resolveOperationCount; }
+    unsigned addPutToBase() { return m_putToBaseOperationCount++; }
+    unsigned numberOfPutToBaseOperations() const { return m_putToBaseOperationCount; }
+
+    UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
+    unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
+    UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
+    unsigned numberOfValueProfiles() { return m_valueProfileCount; }
+
+    UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
+    unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
+
+    CodeType codeType() const { return m_codeType; }
+
+    int thisRegister() const { return m_thisRegister; }
+    int activationRegister() const { return m_activationRegister; }
+
+
+    void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
+    {
+        m_propertyAccessInstructions.append(propertyAccessInstruction);
+    }
+
+    size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
+    const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
+
+    typedef Vector<JSValue> ConstantBuffer;
+
+    size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
+    unsigned addConstantBuffer(unsigned length)
+    {
+        createRareDataIfNecessary();
+        unsigned size = m_rareData->m_constantBuffers.size();
+        m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
+        return size;
+    }
+
+    const ConstantBuffer& constantBuffer(unsigned index) const
+    {
+        ASSERT(m_rareData);
+        return m_rareData->m_constantBuffers[index];
+    }
+
+    ConstantBuffer& constantBuffer(unsigned index)
+    {
+        ASSERT(m_rareData);
+        return m_rareData->m_constantBuffers[index];
+    }
+
+    bool hasRareData() const { return m_rareData; }
+
+    int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
+
+    void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
+
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount)
+    {
+        m_features = features;
+        m_hasCapturedVariables = hasCapturedVariables;
+        m_firstLine = firstLine;
+        m_lineCount = lineCount;
+    }
+
+    CodeFeatures codeFeatures() const { return m_features; }
+    bool hasCapturedVariables() const { return m_hasCapturedVariables; }
+    unsigned firstLine() const { return m_firstLine; }
+    unsigned lineCount() const { return m_lineCount; }
+
+protected:
+    UnlinkedCodeBlock(JSGlobalData*, Structure*, CodeType, const ExecutableInfo&);
+    ~UnlinkedCodeBlock();
+
+    void finishCreation(JSGlobalData& globalData)
+    {
+        Base::finishCreation(globalData);
+        if (codeType() == GlobalCode)
+            return;
+        m_symbolTable.set(globalData, this, SharedSymbolTable::create(globalData));
+    }
+
+private:
+
+    void createRareDataIfNecessary()
+    {
+        if (!m_rareData)
+            m_rareData = adoptPtr(new RareData);
+    }
+
+    RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
+
+    int m_numParameters;
+    JSGlobalData* m_globalData;
+
+    int m_thisRegister;
+    int m_argumentsRegister;
+    int m_activationRegister;
+
+    bool m_needsFullScopeChain : 1;
+    bool m_usesEval : 1;
+    bool m_isNumericCompareFunction : 1;
+    bool m_isStrictMode : 1;
+    bool m_isConstructor : 1;
+    bool m_hasCapturedVariables : 1;
+    unsigned m_firstLine;
+    unsigned m_lineCount;
+
+    CodeFeatures m_features;
+    CodeType m_codeType;
+
+    Vector<unsigned> m_jumpTargets;
+
+    // Constant Pools
+    Vector<Identifier> m_identifiers;
+    Vector<WriteBarrier<Unknown> > m_constantRegisters;
+    typedef Vector<WriteBarrier<UnlinkedFunctionExecutable> > FunctionExpressionVector;
+    FunctionExpressionVector m_functionDecls;
+    FunctionExpressionVector m_functionExprs;
+
+    WriteBarrier<SharedSymbolTable> m_symbolTable;
+
+    Vector<LineInfo> m_lineInfo;
+
+    Vector<unsigned> m_propertyAccessInstructions;
+
+#if ENABLE(BYTECODE_COMMENTS)
+    Vector<Comment>  m_bytecodeComments;
+    size_t m_bytecodeCommentIterator;
+#endif
+
+    unsigned m_resolveOperationCount;
+    unsigned m_putToBaseOperationCount;
+    unsigned m_arrayProfileCount;
+    unsigned m_valueProfileCount;
+    unsigned m_llintCallLinkInfoCount;
+
+public:
+    struct RareData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
+
+        // Rare Constants
+        Vector<WriteBarrier<RegExp> > m_regexps;
+
+        // Buffers used for large array literals
+        Vector<ConstantBuffer> m_constantBuffers;
+
+        // Jump Tables
+        Vector<UnlinkedSimpleJumpTable> m_immediateSwitchJumpTables;
+        Vector<UnlinkedSimpleJumpTable> m_characterSwitchJumpTables;
+        Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
+
+        // Expression info - present if debugging.
+    };
+
+private:
+    OwnPtr<RareData> m_rareData;
+    Vector<ExpressionRangeInfo> m_expressionInfo;
+
+protected:
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+public:
+    static const ClassInfo s_info;
+};
+
+class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
+public:
+    typedef UnlinkedCodeBlock Base;
+
+protected:
+    UnlinkedGlobalCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
+        : Base(globalData, structure, codeType, info)
+    {
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
+private:
+    friend class CodeCache;
+    static UnlinkedProgramCodeBlock* create(JSGlobalData* globalData, const ExecutableInfo& info)
+    {
+        UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(globalData->heap)) UnlinkedProgramCodeBlock(globalData, globalData->unlinkedProgramCodeBlockStructure.get(), info);
+        instance->finishCreation(*globalData);
+        return instance;
+    }
+
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static void destroy(JSCell*);
+
+    void addFunctionDeclaration(JSGlobalData& globalData, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
+    {
+        m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(globalData, this, functionExecutable)));
+    }
+
+    void addVariableDeclaration(const Identifier& name, bool isConstant)
+    {
+        m_varDeclarations.append(std::make_pair(name, isConstant));
+    }
+
+    typedef Vector<std::pair<Identifier, bool> > VariableDeclations;
+    typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable> > > FunctionDeclations;
+
+    const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
+    const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+private:
+    UnlinkedProgramCodeBlock(JSGlobalData* globalData, Structure* structure, const ExecutableInfo& info)
+        : Base(globalData, structure, GlobalCode, info)
+    {
+    }
+
+    VariableDeclations m_varDeclarations;
+    FunctionDeclations m_functionDeclarations;
+
+public:
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
+private:
+    friend class CodeCache;
+
+    static UnlinkedEvalCodeBlock* create(JSGlobalData* globalData, const ExecutableInfo& info)
+    {
+        UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(globalData->heap)) UnlinkedEvalCodeBlock(globalData, globalData->unlinkedEvalCodeBlockStructure.get(), info);
+        instance->finishCreation(*globalData);
+        return instance;
+    }
+
+public:
+    typedef UnlinkedGlobalCodeBlock Base;
+    static void destroy(JSCell*);
+
+    const Identifier& variable(unsigned index) { return m_variables[index]; }
+    unsigned numVariables() { return m_variables.size(); }
+    void adoptVariables(Vector<Identifier>& variables)
+    {
+        ASSERT(m_variables.isEmpty());
+        m_variables.swap(variables);
+    }
+
+private:
+    UnlinkedEvalCodeBlock(JSGlobalData* globalData, Structure* structure, const ExecutableInfo& info)
+        : Base(globalData, structure, EvalCode, info)
+    {
+    }
+
+    Vector<Identifier> m_variables;
+
+public:
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
+private:
+    friend class CodeCache;
+
+    static UnlinkedFunctionCodeBlock* create(JSGlobalData* globalData, CodeType codeType, const ExecutableInfo& info)
+    {
+        UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(globalData->heap)) UnlinkedFunctionCodeBlock(globalData, globalData->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
+        instance->finishCreation(*globalData);
+        return instance;
+    }
+
+public:
+    typedef UnlinkedCodeBlock Base;
+    static void destroy(JSCell*);
+
+private:
+    UnlinkedFunctionCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
+        : Base(globalData, structure, codeType, info)
+    {
+    }
+    
+public:
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+    {
+        return Structure::create(globalData, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), &s_info);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    static const ClassInfo s_info;
+};
+
+}
+
+#endif // UnlinkedCodeBlock_h
index 613354d9220f6d8717818b39af2ac1ab1bc8b3b2..b1187255189fc758193f61247b6f9a338c2c71ae 100644 (file)
@@ -158,7 +158,7 @@ bool BytecodeGenerator::dumpsGeneratedCode()
     return s_dumpsGeneratedCode;
 }
 
-JSObject* BytecodeGenerator::generate()
+ParserError BytecodeGenerator::generate()
 {
     SamplingRegion samplingRegion("Bytecode Generation");
     
@@ -169,36 +169,21 @@ JSObject* BytecodeGenerator::generate()
     for (unsigned i = 0; i < m_tryRanges.size(); ++i) {
         TryRange& range = m_tryRanges[i];
         ASSERT(range.tryData->targetScopeDepth != UINT_MAX);
-        HandlerInfo info = {
+        UnlinkedHandlerInfo info = {
             static_cast<uint32_t>(range.start->bind(0, 0)), static_cast<uint32_t>(range.end->bind(0, 0)),
-            static_cast<uint32_t>(range.tryData->target->bind(0, 0)), static_cast<uint32_t>(range.tryData->targetScopeDepth)
-#if ENABLE(JIT)
-            ,
-#if ENABLE(LLINT)
-            CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(llint_op_catch)))
-#else
-            CodeLocationLabel()
-#endif
-#endif
+            static_cast<uint32_t>(range.tryData->target->bind(0, 0)),
+            range.tryData->targetScopeDepth
         };
         m_codeBlock->addExceptionHandler(info);
     }
     
-    m_codeBlock->instructions() = RefCountedArray<Instruction>(m_instructions);
-
-    if (s_dumpsGeneratedCode)
-        m_codeBlock->dump(m_scope->globalObject()->globalExec());
+    m_codeBlock->instructions() = RefCountedArray<UnlinkedInstruction>(m_instructions);
 
-#ifdef NDEBUG
-    if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
-        symbolTable().clear();
-#endif
-
-    m_codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
+    m_codeBlock->shrinkToFit();
 
     if (m_expressionTooDeep)
-        return createOutOfMemoryError(m_scope->globalObject());
-    return 0;
+        return ParserError::OutOfMemory;
+    return ParserError::ErrorNone;
 }
 
 bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
@@ -216,51 +201,32 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe
     return true;
 }
 
-int BytecodeGenerator::addGlobalVar(
-    const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
-{
-    UNUSED_PARAM(functionMode);
-    int index = symbolTable().size();
-    SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
-    if (functionMode == IsFunctionToSpecialize)
-        newEntry.attemptToWatch();
-    SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry);
-    if (!result.isNewEntry) {
-        result.iterator->value.notifyWrite();
-        index = result.iterator->value.getIndex();
-    }
-    return index;
-}
-
 void BytecodeGenerator::preserveLastVar()
 {
     if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
         m_lastVar = &m_calleeRegisters.last();
 }
 
-BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, JSScope* scope, SharedSymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind)
-    : m_shouldEmitDebugHooks(scope->globalObject()->debugger())
-    , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject()))
-    , m_shouldEmitRichSourceInfo(scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()))
-    , m_scope(*scope->globalData(), scope)
-    , m_symbolTable(symbolTable)
+BytecodeGenerator::BytecodeGenerator(JSGlobalData& globalData, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
+    : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(profilerMode == ProfilerOn)
 #if ENABLE(BYTECODE_COMMENTS)
     , m_currentCommentString(0)
 #endif
+    , m_symbolTable(0)
     , m_scopeNode(programNode)
-    , m_codeBlock(codeBlock)
+    , m_codeBlock(globalData, codeBlock)
     , m_thisRegister(CallFrame::thisArgumentOffset())
     , m_emptyValueRegister(0)
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
-    , m_baseScopeDepth(0)
     , m_codeType(GlobalCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
     , m_hasCreatedActivation(true)
     , m_firstLazyFunction(0)
     , m_lastLazyFunction(0)
-    , m_globalData(scope->globalData())
+    , m_globalData(&globalData)
     , m_lastOpcodeID(op_end)
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
@@ -269,81 +235,48 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, JSScope* scope, S
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
-    m_globalData->startedCompiling(m_codeBlock);
-    
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
-    codeBlock->setGlobalData(m_globalData);
-    symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());    
     m_codeBlock->setNumParameters(1); // Allocate space for "this"
 
     prependComment("entering Program block");
     emitOpcode(op_enter);
 
-    // FIXME: Move code that modifies the global object to Interpreter::execute.
-    
-    if (compilationKind == OptimizingCompilation)
-        return;
-
-    JSGlobalObject* globalObject = scope->globalObject();
-    ExecState* exec = globalObject->globalExec();
-    
-    BatchedTransitionOptimizer optimizer(*m_globalData, globalObject);
-
     const VarStack& varStack = programNode->varStack();
     const FunctionStack& functionStack = programNode->functionStack();
 
-    size_t newGlobals = varStack.size() + functionStack.size();
-    if (!newGlobals)
-        return;
-    globalObject->addRegisters(newGlobals);
-
     for (size_t i = 0; i < functionStack.size(); ++i) {
         FunctionBodyNode* function = functionStack[i];
-        bool propertyDidExist = 
-            globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
-
-        JSValue value = JSFunction::create(exec, FunctionExecutable::create(*m_globalData, function), scope);
-        int index = addGlobalVar(
-            function->ident(), IsVariable,
-            !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
-        globalObject->registerAt(index).set(*m_globalData, globalObject, value);
+        UnlinkedFunctionExecutable* unlinkedFunction = makeFunction(function);
+        codeBlock->addFunctionDeclaration(*m_globalData, function->ident(), unlinkedFunction);
     }
 
-    for (size_t i = 0; i < varStack.size(); ++i) {
-        if (globalObject->hasProperty(exec, *varStack[i].first))
-            continue;
-        addGlobalVar(
-            *varStack[i].first,
-            (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
-            NotFunctionOrNotSpecializable);
-    }
+    for (size_t i = 0; i < varStack.size(); ++i)
+        codeBlock->addVariableDeclaration(*varStack[i].first, !!(varStack[i].second & DeclarationStacks::IsConstant));
+
 }
 
-BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* scope, SharedSymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind)
-    : m_shouldEmitDebugHooks(scope->globalObject()->debugger())
-    , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject()))
-    , m_shouldEmitRichSourceInfo(scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()))
-    , m_scope(*scope->globalData(), scope)
-    , m_symbolTable(symbolTable)
+BytecodeGenerator::BytecodeGenerator(JSGlobalData& globalData, FunctionBodyNode* functionBody, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
+    : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(profilerMode == ProfilerOn)
+    , m_symbolTable(codeBlock->symbolTable())
 #if ENABLE(BYTECODE_COMMENTS)
     , m_currentCommentString(0)
 #endif
     , m_scopeNode(functionBody)
-    , m_codeBlock(codeBlock)
+    , m_codeBlock(globalData, codeBlock)
     , m_activationRegister(0)
     , m_emptyValueRegister(0)
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
-    , m_baseScopeDepth(0)
     , m_codeType(FunctionCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
     , m_hasCreatedActivation(false)
     , m_firstLazyFunction(0)
     , m_lastLazyFunction(0)
-    , m_globalData(scope->globalData())
+    , m_globalData(&globalData)
     , m_lastOpcodeID(op_end)
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
@@ -352,14 +285,11 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
-    m_globalData->startedCompiling(m_codeBlock);
-
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
-    codeBlock->setGlobalData(m_globalData);
-    symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
-    symbolTable->setParameterCountIncludingThis(functionBody->parameters()->size() + 1);
+    m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
+    m_symbolTable->setParameterCountIncludingThis(functionBody->parameters()->size() + 1);
 
     prependComment("entering Function block");
     emitOpcode(op_enter);
@@ -370,7 +300,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
         m_codeBlock->setActivationRegister(m_activationRegister->index());
     }
 
-    symbolTable->setCaptureStart(m_codeBlock->m_numVars);
+    m_symbolTable->setCaptureStart(m_codeBlock->m_numVars);
 
     if (functionBody->usesArguments() || codeBlock->usesEval() || m_shouldEmitDebugHooks) { // May reify arguments object.
         RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
@@ -420,7 +350,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
     }
 
     if (capturesAnyArgumentByName && !codeBlock->isStrictMode()) {
-        size_t parameterCount = symbolTable->parameterCount();
+        size_t parameterCount = m_symbolTable->parameterCount();
         OwnArrayPtr<SlowArgument> slowArguments = adoptArrayPtr(new SlowArgument[parameterCount]);
         for (size_t i = 0; i < parameterCount; ++i) {
             if (!capturedArguments[i]) {
@@ -431,7 +361,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
             slowArguments[i].status = SlowArgument::Captured;
             slowArguments[i].index = capturedArguments[i]->index();
         }
-        symbolTable->setSlowArguments(slowArguments.release());
+        m_symbolTable->setSlowArguments(slowArguments.release());
     }
 
     RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var.
@@ -472,7 +402,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
         instructions().append(m_activationRegister->index());
     }
 
-    symbolTable->setCaptureEnd(codeBlock->m_numVars);
+    m_symbolTable->setCaptureEnd(codeBlock->m_numVars);
 
     m_firstLazyFunction = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
@@ -500,7 +430,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
     }
 
     if (shouldCaptureAllTheThings)
-        symbolTable->setCaptureEnd(codeBlock->m_numVars);
+        m_symbolTable->setCaptureEnd(codeBlock->m_numVars);
 
     FunctionParameters& parameters = *functionBody->parameters();
     m_parameters.grow(parameters.size() + 1); // reserve space for "this"
@@ -530,35 +460,32 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
         emitOpcode(op_create_this);
         instructions().append(m_thisRegister.index());
     } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
-        ValueProfile* profile = emitProfiledOpcode(op_convert_this);
+        UnlinkedValueProfile profile = emitProfiledOpcode(op_convert_this);
         instructions().append(m_thisRegister.index());
         instructions().append(profile);
     }
 }
 
-BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SharedSymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind)
-    : m_shouldEmitDebugHooks(scope->globalObject()->debugger())
-    , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject()))
-    , m_shouldEmitRichSourceInfo(scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()))
-    , m_scope(*scope->globalData(), scope)
-    , m_symbolTable(symbolTable)
+BytecodeGenerator::BytecodeGenerator(JSGlobalData& globalData, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
+    : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn)
+    , m_shouldEmitProfileHooks(profilerMode == ProfilerOn)
+    , m_symbolTable(codeBlock->symbolTable())
 #if ENABLE(BYTECODE_COMMENTS)
     , m_currentCommentString(0)
 #endif
     , m_scopeNode(evalNode)
-    , m_codeBlock(codeBlock)
+    , m_codeBlock(globalData, codeBlock)
     , m_thisRegister(CallFrame::thisArgumentOffset())
     , m_emptyValueRegister(0)
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
-    , m_baseScopeDepth(codeBlock->baseScopeDepth())
     , m_codeType(EvalCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
     , m_hasCreatedActivation(true)
     , m_firstLazyFunction(0)
     , m_lastLazyFunction(0)
-    , m_globalData(scope->globalData())
+    , m_globalData(&globalData)
     , m_lastOpcodeID(op_end)
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
@@ -567,13 +494,9 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SharedS
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
-    m_globalData->startedCompiling(m_codeBlock);
-
-    if (m_shouldEmitDebugHooks || m_baseScopeDepth)
-        m_codeBlock->setNeedsFullScopeChain(true);
+    m_codeBlock->setNeedsFullScopeChain(true);
 
-    codeBlock->setGlobalData(m_globalData);
-    symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());    
+    m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
     m_codeBlock->setNumParameters(1);
 
     prependComment("entering Eval block");
@@ -581,7 +504,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SharedS
 
     const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i)
-        m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i]));
+        m_codeBlock->addFunctionDecl(makeFunction(functionStack[i]));
 
     const DeclarationStacks::VarStack& varStack = evalNode->varStack();
     unsigned numVariables = varStack.size();
@@ -595,7 +518,6 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SharedS
 
 BytecodeGenerator::~BytecodeGenerator()
 {
-    m_globalData->finishedCompiling(m_codeBlock);
 }
 
 RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
@@ -618,17 +540,6 @@ RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
         instructions().append(addConstant(functionBodyNode->ident()));
         instructions().append(m_calleeRegister.index());
         instructions().append(ReadOnly | DontDelete);
-
-        // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
-        m_scope.set(*globalData(),
-            JSNameScope::create(
-                m_scope->globalObject()->globalExec(),
-                functionBodyNode->ident(),
-                jsUndefined(),
-                ReadOnly | DontDelete,
-                m_scope.get()
-            )
-        );
         return 0;
     }
 
@@ -772,7 +683,7 @@ void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
     m_lastOpcodePosition = opcodePosition;
 #endif
     emitComment();
-    instructions().append(globalData()->interpreter->getOpcode(opcodeID));
+    instructions().append(opcodeID);
     m_lastOpcodeID = opcodeID;
 }
 
@@ -796,21 +707,21 @@ void BytecodeGenerator::prependComment(const char* string)
 }
 #endif
 
-ArrayProfile* BytecodeGenerator::newArrayProfile()
+UnlinkedArrayProfile BytecodeGenerator::newArrayProfile()
 {
 #if ENABLE(VALUE_PROFILER)
-    return m_codeBlock->addArrayProfile(instructions().size());
+    return m_codeBlock->addArrayProfile();
 #else
     return 0;
 #endif
 }
 
-ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
+UnlinkedValueProfile BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
 {
 #if ENABLE(VALUE_PROFILER)
-    ValueProfile* result = m_codeBlock->addValueProfile(instructions().size());
+    UnlinkedValueProfile result = m_codeBlock->addValueProfile();
 #else
-    ValueProfile* result = 0;
+    UnlinkedValueProfile result = 0;
 #endif
     emitOpcode(opcodeID);
     return result;
@@ -840,14 +751,6 @@ void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
     srcIndex = instructions().at(size - 1).u.operand;
 }
 
-void BytecodeGenerator::retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex)
-{
-    ASSERT(instructions().size() >= 3);
-    size_t size = instructions().size();
-    dstPointer = instructions().at(size - 2).u.registerPointer;
-    srcIndex = instructions().at(size - 1).u.operand;
-}
-
 void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
 {
     ASSERT(instructions().size() >= 4);
@@ -1336,7 +1239,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
         return ResolveResult::registerResolve(thisRegister(), ResolveResult::ReadOnlyFlag);
 
     // Check if the property should be allocated in a register.
-    if (m_codeType != GlobalCode && shouldOptimizeLocals()) {
+    if (m_codeType != GlobalCode && shouldOptimizeLocals() && m_symbolTable) {
         SymbolTableEntry entry = symbolTable().get(property.impl());
         if (!entry.isNull()) {
             if (property == propertyNames().arguments)
@@ -1352,7 +1255,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
 ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
 {
     // Register-allocated const declarations.
-    if (m_codeType != EvalCode && m_codeType != GlobalCode) {
+    if (m_codeType != EvalCode && m_codeType != GlobalCode && m_symbolTable) {
         SymbolTableEntry entry = symbolTable().get(property.impl());
         if (!entry.isNull()) {
             unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0;
@@ -1394,7 +1297,7 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult&
     if (resolveResult.isRegister())
         return emitGetLocalVar(dst, resolveResult, property);
 
-    ValueProfile* profile = emitProfiledOpcode(op_resolve);
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     instructions().append(getResolveOperations(property));
@@ -1406,7 +1309,7 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const ResolveRes
 {
     ASSERT_UNUSED(resolveResult, !resolveResult.isRegister());
     // We can't optimise at all :-(
-    ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_base);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     instructions().append(false);
@@ -1420,7 +1323,7 @@ RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Reso
 {
     ASSERT_UNUSED(resolveResult, !resolveResult.isRegister());
     // We can't optimise at all :-(
-    ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_base);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     instructions().append(m_codeBlock->isStrictMode());
@@ -1435,7 +1338,7 @@ RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Reso
 RegisterID* BytecodeGenerator::emitResolveWithBaseForPut(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property, NonlocalResolveInfo& verifier)
 {
     ASSERT_UNUSED(resolveResult, !resolveResult.isRegister());
-    ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_with_base);
     instructions().append(baseDst->index());
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
@@ -1455,7 +1358,7 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
         return baseDst;
     }
 
-    ValueProfile* profile = emitProfiledOpcode(op_resolve_with_this);
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_with_this);
     instructions().append(baseDst->index());
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
@@ -1482,23 +1385,11 @@ RegisterID* BytecodeGenerator::emitGetLocalVar(RegisterID* dst, const ResolveRes
 RegisterID* BytecodeGenerator::emitInitGlobalConst(const Identifier& identifier, RegisterID* value)
 {
     ASSERT(m_codeType == GlobalCode);
-    JSGlobalObject* globalObject = m_codeBlock->globalObject();
-    SymbolTableEntry entry = globalObject->symbolTable()->get(identifier.impl());
-    if (entry.isNull())
-        return 0;
-    
-    if (entry.couldBeWatched()) {
-        emitOpcode(op_init_global_const_check);
-        instructions().append(&globalObject->registerAt(entry.getIndex()));
-        instructions().append(value->index());
-        instructions().append(entry.addressOfIsWatched());
-        instructions().append(addConstant(identifier));
-        return value;
-    }
-    
-    emitOpcode(op_init_global_const);
-    instructions().append(&globalObject->registerAt(entry.getIndex()));
+    emitOpcode(op_init_global_const_nop);
+    instructions().append(0);
     instructions().append(value->index());
+    instructions().append(0);
+    instructions().append(addConstant(identifier));
     return value;
 }
 
@@ -1506,7 +1397,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
 {
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 
-    ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(addConstant(property));
@@ -1592,8 +1483,8 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
 
 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
-    ArrayProfile* arrayProfile = newArrayProfile();
-    ValueProfile* profile = emitProfiledOpcode(op_get_argument_by_val);
+    UnlinkedArrayProfile arrayProfile = newArrayProfile();
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_get_argument_by_val);
     instructions().append(dst->index());
     ASSERT(base->index() == m_codeBlock->argumentsRegister());
     instructions().append(base->index());
@@ -1618,8 +1509,8 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
             return dst;
         }
     }
-    ArrayProfile* arrayProfile = newArrayProfile();
-    ValueProfile* profile = emitProfiledOpcode(op_get_by_val);
+    UnlinkedArrayProfile arrayProfile = newArrayProfile();
+    UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(property->index());
@@ -1630,7 +1521,7 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
 
 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
 {
-    ArrayProfile* arrayProfile = newArrayProfile();
+    UnlinkedArrayProfile arrayProfile = newArrayProfile();
     emitOpcode(op_put_by_val);
     instructions().append(base->index());
     instructions().append(property->index());
@@ -1700,7 +1591,7 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
         if (!hadVariableExpression) {
             ASSERT(length == checkLength);
             unsigned constantBufferIndex = addConstantBuffer(length);
-            JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex);
+            JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex).data();
             unsigned index = 0;
             for (ElementNode* n = elements; index < length; n = n->next()) {
                 if (n->value()->isNumber())
@@ -1736,14 +1627,14 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
 
 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
-    return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function)), false);
+    return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(function)), false);
 }
 
 RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
     FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0);
     if (ptr.isNewEntry)
-        ptr.iterator->value = m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function));
+        ptr.iterator->value = m_codeBlock->addFunctionDecl(makeFunction(function));
     return emitNewFunctionInternal(dst, ptr.iterator->value, true);
 }
 
@@ -1768,7 +1659,7 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
     FunctionBodyNode* function = n->body();
-    unsigned index = m_codeBlock->addFunctionExpr(FunctionExecutable::create(*m_globalData, function));
+    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(function));
     
     createActivationIfNecessary();
     emitOpcode(op_new_func_exp);
@@ -1919,7 +1810,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
     
     // Emit call.
-    ArrayProfile* arrayProfile = newArrayProfile();
+    UnlinkedArrayProfile arrayProfile = newArrayProfile();
     emitOpcode(opcodeID);
     instructions().append(func->index()); // func
     instructions().append(callArguments.argumentCountIncludingThis()); // argCount
@@ -1931,7 +1822,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
 #endif
     instructions().append(arrayProfile);
     if (dst != ignoredResult()) {
-        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
+        UnlinkedValueProfile profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
         instructions().append(profile);
     }
@@ -1964,7 +1855,7 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
     instructions().append(arguments->index());
     instructions().append(firstFreeRegister->index());
     if (dst != ignoredResult()) {
-        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
+        UnlinkedValueProfile profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index());
         instructions().append(profile);
     }
@@ -2047,7 +1938,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
 #endif
     instructions().append(0);
     if (dst != ignoredResult()) {
-        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
+        UnlinkedValueProfile profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
         instructions().append(profile);
     }
@@ -2426,7 +2317,7 @@ RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID*
     m_tryContextStack.removeLast();
     
     emitLabel(tryRange.tryData->target.get());
-    tryRange.tryData->targetScopeDepth = m_dynamicScopeDepth + m_baseScopeDepth;
+    tryRange.tryData->targetScopeDepth = m_dynamicScopeDepth;
 
     emitOpcode(op_catch);
     instructions().append(targetRegister->index());
@@ -2435,8 +2326,9 @@ RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID*
 
 void BytecodeGenerator::emitThrowReferenceError(const String& message)
 {
-    emitOpcode(op_throw_reference_error);
+    emitOpcode(op_throw_static_error);
     instructions().append(addConstantValue(jsString(globalData(), message))->index());
+    instructions().append(true);
 }
 
 void BytecodeGenerator::emitPushNameScope(const Identifier& property, RegisterID* value, unsigned attributes)
@@ -2487,7 +2379,7 @@ static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t
     return key - min;
 }
 
-static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
+static void prepareJumpTableForImmediateSwitch(UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
 {
     jumpTable.min = min;
     jumpTable.branchOffsets.resize(max - min + 1);
@@ -2513,7 +2405,7 @@ static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t
     return key - min;
 }
 
-static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
+static void prepareJumpTableForCharacterSwitch(UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
 {
     jumpTable.min = min;
     jumpTable.branchOffsets.resize(max - min + 1);
@@ -2526,7 +2418,7 @@ static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32
     }
 }
 
-static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
+static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
 {
     for (uint32_t i = 0; i < clauseCount; ++i) {
         // We're emitting this after the clause labels should have been fixed, so 
@@ -2535,9 +2427,7 @@ static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t
         
         ASSERT(nodes[i]->isString());
         StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
-        OffsetLocation location;
-        location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3);
-        jumpTable.offsetTable.add(clause, location);
+        jumpTable.offsetTable.add(clause, labels[i]->bind(switchAddress, switchAddress + 3));
     }
 }
 
@@ -2549,20 +2439,20 @@ void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, E
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
         instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
 
-        SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
+        UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
         prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
         instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
         
-        SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
+        UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
         prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
     } else {
         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
         instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
 
-        StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
+        UnlinkedStringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
         prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
     }
 }
@@ -2594,9 +2484,9 @@ void BytecodeGenerator::emitReadOnlyExceptionIfNeeded()
 {
     if (!isStrictMode())
         return;
-
-    RefPtr<RegisterID> error = emitLoad(newTemporary(), JSValue(createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError)));
-    emitThrow(error.get());
+    emitOpcode(op_throw_static_error);
+    instructions().append(addConstantValue(jsString(globalData(), StrictModeReadonlyPropertyWriteError))->index());
+    instructions().append(false);
 }
 
 } // namespace JSC
index 1fccdebefecfa3769e3a9d0b386a113bb8c64ec3..828726dee3226060479f5be1475110f3f7713c2c 100644 (file)
@@ -41,6 +41,7 @@
 #include "SymbolTable.h"
 #include "Debugger.h"
 #include "Nodes.h"
+#include "UnlinkedCodeBlock.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/SegmentedVector.h>
 #include <wtf/Vector.h>
@@ -211,18 +212,18 @@ namespace JSC {
         JS_EXPORT_PRIVATE static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
         static bool dumpsGeneratedCode();
 
-        BytecodeGenerator(ProgramNode*, JSScope*, SharedSymbolTable*, ProgramCodeBlock*, CompilationKind);
-        BytecodeGenerator(FunctionBodyNode*, JSScope*, SharedSymbolTable*, CodeBlock*, CompilationKind);
-        BytecodeGenerator(EvalNode*, JSScope*, SharedSymbolTable*, EvalCodeBlock*, CompilationKind);
+        BytecodeGenerator(JSGlobalData&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);
+        BytecodeGenerator(JSGlobalData&, FunctionBodyNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);
+        BytecodeGenerator(JSGlobalData&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);
 
         ~BytecodeGenerator();
         
         JSGlobalData* globalData() const { return m_globalData; }
         const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
 
-        bool isConstructor() { return m_codeBlock->m_isConstructor; }
+        bool isConstructor() { return m_codeBlock->isConstructor(); }
 
-        JSObject* generate();
+        ParserError generate();
 
         bool isArgumentNumber(const Identifier&, int);
 
@@ -332,10 +333,7 @@ namespace JSC {
 
         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
         {
-            if (!m_shouldEmitRichSourceInfo)
-                return;
-
-            divot -= m_codeBlock->sourceOffset();
+            divot -= m_scopeNode->source().startOffset();
             if (divot > ExpressionRangeInfo::MaxDivot) {
                 // Overflow has occurred, we can only give line number info for errors for this region
                 divot = 0;
@@ -508,8 +506,6 @@ namespace JSC {
         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
         
         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
-        
-        JSScope* scope() const { return m_scope.get(); }
 
     private:
         friend class Label;
@@ -527,11 +523,10 @@ namespace JSC {
 #endif
 
         void emitOpcode(OpcodeID);
-        ArrayProfile* newArrayProfile();
-        ValueProfile* emitProfiledOpcode(OpcodeID);
+        UnlinkedArrayProfile newArrayProfile();
+        UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
-        void retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex);
         ALWAYS_INLINE void rewindBinaryOp();
         ALWAYS_INLINE void rewindUnaryOp();
 
@@ -574,10 +569,6 @@ namespace JSC {
         }
 
         // Returns the index of the added var.
-        enum ConstantMode { IsConstant, IsVariable };
-        enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
-        int addGlobalVar(const Identifier&, ConstantMode, FunctionMode);
-
         void addParameter(const Identifier&, int parameterIndex);
         RegisterID* resolveCallee(FunctionBodyNode*);
         void addCallee(FunctionBodyNode*, RegisterID*);
@@ -604,17 +595,22 @@ namespace JSC {
 
         unsigned addConstantBuffer(unsigned length);
         
+        UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
+        {
+            return UnlinkedFunctionExecutable::create(m_globalData, m_scopeNode->source(), body);
+        }
+
         JSString* addStringConstant(const Identifier&);
 
         void addLineInfo(unsigned lineNo)
         {
-            m_codeBlock->addLineInfo(instructions().size(), lineNo);
+            m_codeBlock->addLineInfo(instructions().size(), lineNo - m_scopeNode->firstLine());
         }
 
         RegisterID* emitInitLazyRegister(RegisterID*);
 
     public:
-        Vector<Instruction>& instructions() { return m_instructions; }
+        Vector<UnlinkedInstruction>& instructions() { return m_instructions; }
 
         SharedSymbolTable& symbolTable() { return *m_symbolTable; }
 #if ENABLE(BYTECODE_COMMENTS)
@@ -652,13 +648,11 @@ namespace JSC {
         void createActivationIfNecessary();
         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
         
-        Vector<Instruction> m_instructions;
+        Vector<UnlinkedInstruction> m_instructions;
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
-        bool m_shouldEmitRichSourceInfo;
 
-        Strong<JSScope> m_scope;
         SharedSymbolTable* m_symbolTable;
 
 #if ENABLE(BYTECODE_COMMENTS)
@@ -667,7 +661,7 @@ namespace JSC {
 #endif
 
         ScopeNode* m_scopeNode;
-        CodeBlock* m_codeBlock;
+        Strong<UnlinkedCodeBlock> m_codeBlock;
 
         // Some of these objects keep pointers to one another. They are arranged
         // to ensure a sane destruction order that avoids references to freed memory.
@@ -685,7 +679,6 @@ namespace JSC {
         RefPtr<RegisterID> m_lastVar;
         int m_finallyDepth;
         int m_dynamicScopeDepth;
-        int m_baseScopeDepth;
         CodeType m_codeType;
 
         Vector<ControlFlowContext> m_scopeContextStack;
index 3731b047302da3912e5788a60add12cb64c8b4e9..b147291468a2b05098421b8d2b70eef094566fdd 100644 (file)
@@ -80,6 +80,7 @@ inline void Recompiler::operator()(JSCell* cell)
 
     ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec();
     executable->clearCodeIfNotCompiling();
+    executable->clearUnlinkedCodeIfNotCompiling();
     if (m_debugger == function->scope()->globalObject()->debugger())
         m_sourceProviders.add(executable->source().provider(), exec);
 }
index 6b9056e54a18c6bfd001303b8f4e4ee65ad064c7..e1837b041d7290659c15096e4f5ea58658b4fcb9 100644 (file)
@@ -158,7 +158,7 @@ public:
             // Nope, so try to parse one.
             JSObject* exception;
             value.owned = true;
-            value.codeBlock = key.executable()->produceCodeBlockFor(scope, OptimizingCompilation, key.kind(), exception).leakPtr();
+            value.codeBlock = key.executable()->produceCodeBlockFor(scope, key.kind(), exception).leakPtr();
         }
         
         // Check if there is any reason to reject this from our cache. If so, then
index 9a41033e9c80a1b07dc9592c201fe054dd854111..70aa2b63786320de93fe69b9e3a4483cacb3fdb9 100644 (file)
@@ -2614,6 +2614,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NEXT_OPCODE(op_put_by_id);
         }
 
+        case op_init_global_const_nop: {
+            NEXT_OPCODE(op_init_global_const_nop);
+        }
+
         case op_init_global_const: {
             NodeIndex value = get(currentInstruction[2].u.operand);
             addToGraph(
@@ -2851,10 +2855,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             addToGraph(Throw, get(currentInstruction[1].u.operand));
             LAST_OPCODE(op_throw);
             
-        case op_throw_reference_error:
+        case op_throw_static_error:
             flushArgumentsAndCapturedVariables();
             addToGraph(ThrowReferenceError);
-            LAST_OPCODE(op_throw_reference_error);
+            LAST_OPCODE(op_throw_static_error);
             
         case op_call:
             handleCall(interpreter, currentInstruction, Call, CodeForCall);
@@ -3597,7 +3601,7 @@ void ByteCodeParser::parseCodeBlock()
     dataLog("Parsing code block %p. codeType = %s, captureCount = %u, needsFullScopeChain = %s, needsActivation = %s, isStrictMode = %s\n",
             codeBlock,
             codeTypeToString(codeBlock->codeType()),
-            codeBlock->symbolTable()->captureCount(),
+            codeBlock->symbolTable() ? codeBlock->symbolTable()->captureCount() : 0,
             codeBlock->needsFullScopeChain()?"true":"false",
             codeBlock->ownerExecutable()->needsActivation()?"true":"false",
             codeBlock->ownerExecutable()->isStrictMode()?"true":"false");
index 95269e8a082a6123703b35bb0a62df8ebff5deb0..1f9778efef23d33492246d0b22546eb18734d916 100644 (file)
@@ -166,6 +166,7 @@ inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instructi
     case op_put_by_id_transition_direct_out_of_line:
     case op_put_by_id_transition_normal:
     case op_put_by_id_transition_normal_out_of_line:
+    case op_init_global_const_nop:
     case op_init_global_const:
     case op_init_global_const_check:
     case op_jmp:
@@ -199,7 +200,7 @@ inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instructi
     case op_strcat:
     case op_to_primitive:
     case op_throw:
-    case op_throw_reference_error:
+    case op_throw_static_error:
     case op_call:
     case op_construct:
     case op_new_regexp: 
index 13e04388cd6a856d6ea37bbc4f8ef0f66ebdeab4..0e45e230c399cca81c64c62ae9d63ae183e6f361 100644 (file)
@@ -1157,8 +1157,7 @@ JSCell* DFG_OPERATION operationCreateActivation(ExecState* exec)
 {
     JSGlobalData& globalData = exec->globalData();
     NativeCallFrameTracer tracer(&globalData, exec);
-    JSActivation* activation = JSActivation::create(
-        globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
+    JSActivation* activation = JSActivation::create(globalData, exec, exec->codeBlock());
     exec->setScope(activation);
     return activation;
 }
index cd3393aa20c15664b2a44cfc62939c4e2b2cb4ba..c455fc2b189b6ff67a89cd9e56417d1346ca7d86 100644 (file)
@@ -36,6 +36,7 @@
 #include "JSLock.h"
 #include "JSONObject.h"
 #include "Tracing.h"
+#include "UnlinkedCodeBlock.h"
 #include "WeakSetInlines.h"
 #include <algorithm>
 #include <wtf/RAMSize.h>
@@ -484,13 +485,13 @@ void Heap::markRoots(bool fullGC)
             }
         }
 #endif
-    
+
         if (m_globalData->codeBlocksBeingCompiled.size()) {
             GCPHASE(VisitActiveCodeBlock);
             for (size_t i = 0; i < m_globalData->codeBlocksBeingCompiled.size(); i++)
                 m_globalData->codeBlocksBeingCompiled[i]->visitAggregate(visitor);
         }
-    
+
         {
             GCPHASE(VisitMachineRoots);
             MARK_LOG_ROOT(visitor, "C++ Stack");
index 13bd8e493d0d7b3f38e983b3559467c233d5b85c..867481fe3329613ec7a27df33307beaa550883d4 100644 (file)
@@ -74,10 +74,18 @@ inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t c
 inline void* MarkedAllocator::allocate(size_t bytes)
 {
     MarkedBlock::FreeCell* head = m_freeList.head;
-    if (UNLIKELY(!head))
-        return allocateSlowCase(bytes);
+    if (UNLIKELY(!head)) {
+        void* result = allocateSlowCase(bytes);
+#ifndef NDEBUG
+        memset(result, 0xCD, bytes);
+#endif
+        return result;
+    }
     
     m_freeList.head = head->next;
+#ifndef NDEBUG
+    memset(head, 0xCD, bytes);
+#endif
     return head;
 }
 
index 7a30debda4fcdf88cd53ea7ff761ca7f38cb5ac3..3919705d00ea129a6ca2b84cc04fc56fadce93aa 100644 (file)
@@ -294,6 +294,8 @@ ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue* slot)
     if (!cell)
         return;
 
+    validate(cell);
+
     if (m_shouldHashConst && cell->isString()) {
         JSString* string = jsCast<JSString*>(cell);
         if (string->shouldTryHashConst() && string->tryHashConstLock()) {
@@ -355,6 +357,10 @@ void SlotVisitor::validate(JSCell* cell)
                 cell->structure()->structure(), parentClassName, cell, cell->structure(), ourClassName);
         CRASH();
     }
+
+    // Make sure we can walk the ClassInfo chain
+    const ClassInfo* info = cell->classInfo();
+    do { } while ((info = info->parentClass));
 }
 #else
 void SlotVisitor::validate(JSCell*)
index 3e6471b0ff7f509732d9ea8758b03c8ee27d36e2..397ac8474841cceb04128cb0a98d68f8ab8e5b25 100644 (file)
@@ -948,10 +948,13 @@ failedJSONP:
     // object.
 
     // Compile source to bytecode if necessary:
-    JSObject* error = program->compile(callFrame, scope);
-    if (error)
+    if (JSObject* error = program->initalizeGlobalProperties(globalData, callFrame, scope))
         return checkedReturn(throwError(callFrame, error));
-    CodeBlock* codeBlock = &program->generatedBytecode();
+
+    if (JSObject* error = program->compile(callFrame, scope))
+        return checkedReturn(throwError(callFrame, error));
+
+    ProgramCodeBlock* codeBlock = &program->generatedBytecode();
 
     // Push the call frame for this invocation:
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
index 9f91014c8f297422d7f00854f4b353c2364daa8d..3102c7693011e1f394624a86f3e6deea6730cd84 100644 (file)
@@ -335,6 +335,8 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_put_by_index)
         DEFINE_OP(op_put_by_val)
         DEFINE_OP(op_put_getter_setter)
+        case op_init_global_const_nop:
+            NEXT_OPCODE(op_init_global_const_nop);
         DEFINE_OP(op_init_global_const)
         DEFINE_OP(op_init_global_const_check)
 
@@ -371,7 +373,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_tear_off_activation)
         DEFINE_OP(op_tear_off_arguments)
         DEFINE_OP(op_throw)
-        DEFINE_OP(op_throw_reference_error)
+        DEFINE_OP(op_throw_static_error)
         DEFINE_OP(op_to_jsnumber)
         DEFINE_OP(op_to_primitive)
 
index d2595c723f071ba3618e688fae72ac1366c64961..dcf87d3526a68661f5724c3787e505252c22c03e 100644 (file)
@@ -731,7 +731,7 @@ namespace JSC {
         void emit_op_tear_off_activation(Instruction*);
         void emit_op_tear_off_arguments(Instruction*);
         void emit_op_throw(Instruction*);
-        void emit_op_throw_reference_error(Instruction*);
+        void emit_op_throw_static_error(Instruction*);
         void emit_op_to_jsnumber(Instruction*);
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
index 318b4e7aaeb8ab95326ac26f2c2e64100ff2b28f..645c65b281e8c62357faf90ea30e27f46f696ca0 100644 (file)
@@ -75,7 +75,7 @@ inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& code
     return true;
 }
 
-inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, WriteBarrier<SharedSymbolTable>& symbolTable, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
+inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
 {
     JSGlobalData& globalData = exec->globalData();
     
@@ -99,7 +99,6 @@ inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCode
     } else {
         if (codeBlock->alternative()) {
             codeBlock = static_pointer_cast<FunctionCodeBlock>(codeBlock->releaseAlternative());
-            symbolTable.set(exec->globalData(), codeBlock->ownerExecutable(), codeBlock->symbolTable());
             jitCode = oldJITCode;
             jitCodeWithArityCheck = oldJITCodeWithArityCheck;
             return false;
index 07c8ace2a35395edaf8a57653ee1d1e101cbea00..249dcbac9159b18e2e27f0ef0a6a124b587e3522 100644 (file)
@@ -1069,13 +1069,14 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
     jump(regT0);
 }
 
-void JIT::emit_op_throw_reference_error(Instruction* currentInstruction)
+void JIT::emit_op_throw_static_error(Instruction* currentInstruction)
 {
-    JITStubCall stubCall(this, cti_op_throw_reference_error);
+    JITStubCall stubCall(this, cti_op_throw_static_error);
     if (!m_codeBlock->getConstant(currentInstruction[1].u.operand).isNumber())
         stubCall.addArgument(TrustedImm64(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
     else
         stubCall.addArgument(Imm64(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
     stubCall.call();
 }
 
index 44123be198179e1b76b7512824d3a8c93f0ee947..9c5d260ab6ec8dd999a9998e4393b202f606c8ae 100644 (file)
@@ -1401,12 +1401,13 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
     jump(regT0);
 }
 
-void JIT::emit_op_throw_reference_error(Instruction* currentInstruction)
+void JIT::emit_op_throw_static_error(Instruction* currentInstruction)
 {
     unsigned message = currentInstruction[1].u.operand;
 
-    JITStubCall stubCall(this, cti_op_throw_reference_error);
+    JITStubCall stubCall(this, cti_op_throw_static_error);
     stubCall.addArgument(m_codeBlock->getConstant(message));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
     stubCall.call();
 }
 
index 515395b49da4d5a87c4989aa0dfec54921fa2d0d..5ddb98dee50061a11eff8985b3d1817ebc5bad94 100644 (file)
@@ -2144,7 +2144,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSActivation* activation = JSActivation::create(stackFrame.callFrame->globalData(), stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
+    JSActivation* activation = JSActivation::create(stackFrame.callFrame->globalData(), stackFrame.callFrame, stackFrame.callFrame->codeBlock());
     stackFrame.callFrame->setScope(activation);
     return activation;
 }
@@ -3336,13 +3336,16 @@ DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
     baseObj->putDirectAccessor(callFrame, stackFrame.args[1].identifier(), accessor, Accessor);
 }
 
-DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
+DEFINE_STUB_FUNCTION(void, op_throw_static_error)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     String message = stackFrame.args[0].jsValue().toString(callFrame)->value(callFrame);
-    stackFrame.globalData->exception = createReferenceError(callFrame, message);
+    if (stackFrame.args[1].asInt32)
+        stackFrame.globalData->exception = createReferenceError(callFrame, message);
+    else
+        stackFrame.globalData->exception = createTypeError(callFrame, message);
     VM_THROW_EXCEPTION_AT_END();
 }
 
index 3d0ea83df3b0362cc793c5b176f0e1c1459bb113..5761236b14b3ffa9898972997b17905c8ac041f7 100644 (file)
@@ -452,7 +452,7 @@ extern "C" {
     void JIT_STUB cti_op_init_global_const_check(STUB_ARGS_DECLARATION) WTF_INTERNAL;
     void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION) WTF_INTERNAL;
     void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-    void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION) WTF_INTERNAL;
+    void JIT_STUB cti_op_throw_static_error(STUB_ARGS_DECLARATION) WTF_INTERNAL;
 #if ENABLE(DFG_JIT)
     void JIT_STUB cti_optimize(STUB_ARGS_DECLARATION) WTF_INTERNAL;
 #endif
index 8e2dacf4d4a3301ba7588e8a58a91078c4f967a3..eec376b379ae863de6516cc87db36dabc4f391d2 100644 (file)
@@ -103,7 +103,7 @@ void Data::performAssertions(JSGlobalData& globalData)
     ASSERT(ValueNull == TagBitTypeOther);
 #endif
     ASSERT(StringType == 5);
-    ASSERT(ObjectType == 13);
+    ASSERT(ObjectType == 17);
     ASSERT(MasqueradesAsUndefined == 1);
     ASSERT(ImplementsHasInstance == 2);
     ASSERT(ImplementsDefaultHasInstance == 8);
index a4157d3d7cc3e75cb34f127af82ca8c66ea6d30c..ba44bf404148d19ddf7e4dfe848c0402dae58a6a 100644 (file)
@@ -460,7 +460,7 @@ LLINT_SLOW_PATH_DECL(slow_path_create_activation)
 #if LLINT_SLOW_PATH_TRACING
     dataLog("Creating an activation, exec = %p!\n", exec);
 #endif
-    JSActivation* activation = JSActivation::create(globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
+    JSActivation* activation = JSActivation::create(globalData, exec, exec->codeBlock());
     exec->setScope(activation);
     LLINT_RETURN(JSValue(activation));
 }
@@ -1622,10 +1622,13 @@ LLINT_SLOW_PATH_DECL(slow_path_throw)
     LLINT_THROW(LLINT_OP_C(1).jsValue());
 }
 
-LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error)
+LLINT_SLOW_PATH_DECL(slow_path_throw_static_error)
 {
     LLINT_BEGIN();
-    LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
+    if (pc[2].u.operand)
+        LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
+    else
+        LLINT_THROW(createTypeError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_debug)
index f7847684100c65c79e3f2d798da8989a66b67f02..99fbaccfa28231bd0c95e216d87bb744b6e14a88 100644 (file)
@@ -204,7 +204,7 @@ LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_pop_scope);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_push_name_scope);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw);
-LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw_reference_error);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_throw_static_error);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_debug);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_profile_will_call);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_profile_did_call);
index f403b0b6cb3bd3fa00a5c3b5fee80f6a6802a30d..ba5b67df4c879a397c47d43809b49e5e05d9c704 100644 (file)
@@ -96,7 +96,7 @@ const SlowPutArrayStorageShape = 30
 
 # Type constants.
 const StringType = 5
-const ObjectType = 13
+const ObjectType = 17
 
 # Type flags constants.
 const MasqueradesAsUndefined = 1
@@ -1234,10 +1234,10 @@ _llint_op_throw:
     dispatch(2)
 
 
-_llint_op_throw_reference_error:
+_llint_op_throw_static_error:
     traceExecution()
-    callSlowPath(_llint_slow_path_throw_reference_error)
-    dispatch(2)
+    callSlowPath(_llint_slow_path_throw_static_error)
+    dispatch(3)
 
 
 _llint_op_profile_will_call:
@@ -1326,6 +1326,8 @@ _llint_op_put_by_id_replace:
 _llint_op_put_by_id_transition:
     notSupported()
 
+_llint_op_init_global_const_nop:
+    dispatch(5)
 
 # Indicate the end of LLInt.
 _llint_end:
index 891b63d64b9a2d54ff16a5bc7c9d8ac258d16ee8..ffb146247fb570a38baf4615ba8cac3b5bef473d 100644 (file)
@@ -984,7 +984,7 @@ _llint_op_init_global_const:
     writeBarrier(t2, t3)
     storei t2, TagOffset[t0]
     storei t3, PayloadOffset[t0]
-    dispatch(3)
+    dispatch(5)
 
 
 _llint_op_init_global_const_check:
index 5bb0d70ae6e600da91c8f60ee5783fc4f63fa308..c9900b3437e526045a1651ba0216543ab23c6849 100644 (file)
@@ -830,7 +830,7 @@ _llint_op_init_global_const:
     loadConstantOrVariable(t1, t2)
     writeBarrier(t2)
     storeq t2, [t0]
-    dispatch(3)
+    dispatch(5)
 
 
 _llint_op_init_global_const_check:
index 3b0316f8165a0856a3297595ce52125dc0fa632f..615d09eb75d83a79b1baa095db8a2982bec654fb 100644 (file)
@@ -76,6 +76,49 @@ COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
 enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
 enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
 
+struct ParserError {
+    enum ErrorType { ErrorNone, StackOverflow, SyntaxError, EvalError, OutOfMemory } m_type;
+    String m_message;
+    int m_line;
+    ParserError()
+        : m_type(ErrorNone)
+        , m_line(-1)
+    {
+    }
+
+    ParserError(ErrorType type)
+        : m_type(type)
+        , m_line(-1)
+    {
+    }
+
+    ParserError(ErrorType type, String msg, int line)
+        : m_type(type)
+        , m_message(msg)
+        , m_line(line)
+    {
+    }
+
+    JSObject* toErrorObject(JSGlobalObject* globalObject, const SourceCode& source)
+    {
+        switch (m_type) {
+        case ErrorNone:
+            return 0;
+        case SyntaxError:
+            return addErrorInfo(globalObject->globalExec(), createSyntaxError(globalObject, m_message), m_line, source);
+        case EvalError:
+            return createSyntaxError(globalObject, m_message);
+        case StackOverflow:
+            return createStackOverflowError(globalObject);
+        case OutOfMemory:
+            return createOutOfMemoryError(globalObject);
+        }
+        CRASH();
+        return createOutOfMemoryError(globalObject); // Appease Qt bot
+    }
+
+};
+
 template <typename T> inline bool isEvalNode() { return false; }
 template <> inline bool isEvalNode<EvalNode>() { return true; }
 
@@ -370,7 +413,7 @@ public:
     ~Parser();
 
     template <class ParsedNode>
-    PassRefPtr<ParsedNode> parse(JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, JSObject**);
+    PassRefPtr<ParsedNode> parse(ParserError&);
 
 private:
     struct AllowInOverride {
@@ -890,7 +933,7 @@ private:
         return m_lastTokenEnd;
     }
 
-    mutable const JSGlobalData* m_globalData;
+    JSGlobalData* m_globalData;
     const SourceCode* m_source;
     ParserArena* m_arena;
     OwnPtr<LexerType> m_lexer;
@@ -935,12 +978,11 @@ private:
     };
 };
 
+
 template <typename LexerType>
 template <class ParsedNode>
-PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, JSObject** exception)
+PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
 {
-    ASSERT(lexicalGlobalObject);
-    ASSERT(exception && !*exception);
     int errLine;
     String errMsg;
 
@@ -971,7 +1013,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
         JSTokenLocation location;
         location.line = m_lexer->lastLineNumber();
         location.column = m_lexer->currentColumnNumber();
-        result = ParsedNode::create(&lexicalGlobalObject->globalData(),
+        result = ParsedNode::create(m_globalData,
                                     location,
                                     m_sourceElements,
                                     m_varDeclarations ? &m_varDeclarations->data : 0,
@@ -981,7 +1023,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
                                     m_features,
                                     m_numConstants);
         result->setLoc(m_source->firstLine(), m_lastLine, m_lexer->currentColumnNumber());
-    } else if (lexicalGlobalObject) {
+    } else {
         // We can never see a syntax error when reparsing a function, since we should have
         // reported the error when parsing the containing program or eval code. So if we're
         // parsing a function body node, we assume that what actually happened here is that
@@ -989,35 +1031,31 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
         // code we assume that it was a syntax error since running out of stack is much less
         // likely, and we are currently unable to distinguish between the two cases.
         if (isFunctionBodyNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow)
-            *exception = createStackOverflowError(lexicalGlobalObject);
+            error = ParserError::StackOverflow;
         else if (isEvalNode<ParsedNode>())
-            *exception = createSyntaxError(lexicalGlobalObject, errMsg);
+            error = ParserError(ParserError::EvalError, errMsg, errLine);
         else
-            *exception = addErrorInfo(lexicalGlobalObject->globalExec(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source);
+            error = ParserError(ParserError::SyntaxError, errMsg, errLine);
     }
 
-    if (debugger && !ParsedNode::scopeIsFunction)
-        debugger->sourceParsed(debuggerExecState, m_source->provider(), errLine, errMsg);
-
     m_arena->reset();
 
     return result.release();
 }
 
 template <class ParsedNode>
-PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)
+PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error)
 {
     SamplingRegion samplingRegion("Parsing");
 
     ASSERT(!source.provider()->source().isNull());
-
     if (source.provider()->source().is8Bit()) {
         Parser< Lexer<LChar> > parser(globalData, source, parameters, name, strictness, parserMode);
-        return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
+        return parser.parse<ParsedNode>(error);
     }
     Parser< Lexer<UChar> > parser(globalData, source, parameters, name, strictness, parserMode);
-    return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
+    return parser.parse<ParsedNode>(error);
 }
 
-} // namespace 
+} // namespace
 #endif
diff --git a/Source/JavaScriptCore/parser/ParserModes.h b/Source/JavaScriptCore/parser/ParserModes.h
new file mode 100644 (file)
index 0000000..41fb7fd
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``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 ITS 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 ParserModes_h
+#define ParserModes_h
+
+namespace JSC {
+
+enum JSParserStrictness { JSParseNormal, JSParseStrict };
+enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
+
+enum ProfilerMode { ProfilerOff, ProfilerOn };
+enum DebuggerMode { DebuggerOff, DebuggerOn };
+
+}
+
+#endif
index 6e6cec114d445e37865fec8c391df5b51dec517a..14191b95d7d3b5bcc041b11975eb55156cddc786 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef ParserTokens_h
 #define ParserTokens_h
 
+#include "ParserModes.h"
+
 namespace JSC {
 
 class Identifier;
@@ -161,9 +163,6 @@ struct JSToken {
     JSTokenLocation m_location;
 };
 
-enum JSParserStrictness { JSParseNormal, JSParseStrict };
-enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
-    
 }
 
 
index 7c8b69bd12451ac1b66760ffdc6b71fdbfe55c2f..7961d4bc832db13d3ebf8f8cd2be0a36a399c655 100644 (file)
@@ -267,8 +267,7 @@ namespace JSC {
         m_overrodeCallee = false;
         m_overrodeCaller = false;
         m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode();
-
-        ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable()->slowArguments());
+        ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->slowArguments());
 
         // The bytecode generator omits op_tear_off_activation in cases of no
         // declared parameters, so we need to tear off immediately.
diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp
new file mode 100644 (file)
index 0000000..4de760e
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2012 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 "CodeCache.h"
+
+#include "BytecodeGenerator.h"
+#include "CodeSpecializationKind.h"
+#include "Parser.h"
+#include "StrongInlines.h"
+#include "UnlinkedCodeBlock.h"
+
+namespace JSC {
+
+CodeCache::CodeCache()
+    : m_randomGenerator(static_cast<uint32_t>(randomNumber() * UINT32_MAX))
+{
+}
+
+CodeCache::~CodeCache()
+{
+}
+
+CodeCache::CodeBlockKey CodeCache::makeCodeBlockKey(const SourceCode& source, CodeCache::CodeType type, JSParserStrictness strictness)
+{
+    return std::make_pair(source.toString(), (type << 1) | strictness);
+}
+
+template <typename T> struct CacheTypes { };
+
+template <> struct CacheTypes<UnlinkedProgramCodeBlock> {
+    typedef JSC::ProgramNode RootNode;
+    static const CodeCache::CodeType codeType = CodeCache::ProgramType;
+};
+
+template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
+    typedef JSC::EvalNode RootNode;
+    static const CodeCache::CodeType codeType = CodeCache::EvalType;
+};
+
+template <class UnlinkedCodeBlockType, class ExecutableType>
+UnlinkedCodeBlockType* CodeCache::getCodeBlock(JSGlobalData& globalData, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+    CodeBlockKey key = makeCodeBlockKey(source, CacheTypes<UnlinkedCodeBlockType>::codeType, strictness);
+    bool storeInCache = false;
+    if (debuggerMode == DebuggerOff && profilerMode == ProfilerOff) {
+        CodeBlockIndicesMap::iterator result = m_cachedCodeBlockIndices.find(key);
+        if (result != m_cachedCodeBlockIndices.end()) {
+            UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(m_cachedCodeBlocks[result->value].second.get());
+            unsigned firstLine = source.firstLine() + unlinkedCode->firstLine();
+            executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount());
+            return unlinkedCode;
+        }
+        storeInCache = true;
+    }
+
+    typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
+    RefPtr<RootNode> rootNode = parse<RootNode>(&globalData, source, 0, Identifier(), strictness, JSParseProgramCode, error);
+    if (!rootNode)
+        return 0;
+    executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine());
+
+    UnlinkedCodeBlockType* unlinkedCode = UnlinkedCodeBlockType::create(&globalData, executable->executableInfo());
+    unlinkedCode->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), rootNode->lastLine() - rootNode->lineNo());
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(globalData, rootNode.get(), unlinkedCode, debuggerMode, profilerMode)));
+    error = generator->generate();
+    rootNode->destroyData();
+    if (error.m_type != ParserError::ErrorNone)
+        return 0;
+
+    if (storeInCache) {
+        size_t index = m_randomGenerator.getUint32() % kMaxCodeBlockEntries;
+        if (m_cachedCodeBlocks[index].second)
+            m_cachedCodeBlockIndices.remove(m_cachedCodeBlocks[index].first);
+        m_cachedCodeBlockIndices.set(key, index);
+        m_cachedCodeBlocks[index].second.set(globalData, unlinkedCode);
+        m_cachedCodeBlocks[index].first = key;
+    }
+
+    return unlinkedCode;
+}
+
+UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(JSGlobalData& globalData, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+    return getCodeBlock<UnlinkedProgramCodeBlock>(globalData, executable, source, strictness, debuggerMode, profilerMode, error);
+}
+
+UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(JSGlobalData& globalData, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+    return getCodeBlock<UnlinkedEvalCodeBlock>(globalData, executable, source, strictness, debuggerMode, profilerMode, error);
+}
+
+UnlinkedFunctionCodeBlock* CodeCache::generateFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&globalData, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error);
+
+    if (!body) {
+        ASSERT(error.m_type != ParserError::ErrorNone);
+        return 0;
+    }
+
+    if (executable->forceUsesArguments())
+        body->setUsesArguments();
+    body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle());
+    executable->recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
+    
+    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&globalData, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct));
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(globalData, body.get(), result, debuggerMode, profilerMode)));
+    error = generator->generate();
+    body->destroyData();
+    if (error.m_type != ParserError::ErrorNone)
+        return 0;
+    return result;
+}
+
+UnlinkedFunctionCodeBlock* CodeCache::getFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+    return generateFunctionCodeBlock(globalData, executable, source, kind, debuggerMode, profilerMode, error);
+}
+
+CodeCache::GlobalFunctionKey CodeCache::makeGlobalFunctionKey(const SourceCode& source, const String& name)
+{
+    return GlobalFunctionKey(source.toString(), name);
+}
+
+UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, ParserError& error)
+{
+    GlobalFunctionKey key = makeGlobalFunctionKey(source, name.string());
+    GlobalFunctionIndicesMap::iterator result = m_cachedGlobalFunctionIndices.find(key);
+    if (result != m_cachedGlobalFunctionIndices.end())
+        return m_cachedGlobalFunctions[result->value].second.get();
+
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&globalData, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+    if (!program) {
+        ASSERT(error.m_type != ParserError::ErrorNone);
+        return 0;
+    }
+
+    // This function assumes an input string that would result in a single anonymous function expression.
+    StatementNode* exprStatement = program->singleStatement();
+    ASSERT(exprStatement);
+    ASSERT(exprStatement->isExprStatement());
+    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+    ASSERT(funcExpr);
+    ASSERT(funcExpr->isFuncExprNode());
+    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+    ASSERT(body);
+    ASSERT(body->ident().isNull());
+
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&globalData, source, body);
+    functionExecutable->m_nameValue.set(globalData, functionExecutable, jsString(&globalData, name.string()));
+
+    size_t index = m_randomGenerator.getUint32() % kMaxGlobalFunctionEntries;
+    if (m_cachedGlobalFunctions[index].second)
+        m_cachedGlobalFunctionIndices.remove(m_cachedGlobalFunctions[index].first);
+    m_cachedGlobalFunctionIndices.set(key, index);
+    m_cachedGlobalFunctions[index].second.set(globalData, functionExecutable);
+    m_cachedGlobalFunctions[index].first = key;
+
+    return functionExecutable;
+}
+
+}
diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h
new file mode 100644 (file)
index 0000000..4d46171
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 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 CodeCache_h
+#define CodeCache_h
+
+#include "CodeSpecializationKind.h"
+#include "ParserModes.h"
+#include "Strong.h"
+#include "WeakRandom.h"
+
+#include <wtf/FixedArray.h>
+#include <wtf/Forward.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class EvalExecutable;
+class Identifier;
+class ProgramExecutable;
+class UnlinkedCodeBlock;
+class UnlinkedEvalCodeBlock;
+class UnlinkedFunctionCodeBlock;
+class UnlinkedFunctionExecutable;
+class UnlinkedProgramCodeBlock;
+class JSGlobalData;
+struct ParserError;
+class SourceCode;
+class SourceProvider;
+
+class CodeCache {
+public:
+    static PassOwnPtr<CodeCache> create() { return adoptPtr(new CodeCache); }
+
+    UnlinkedProgramCodeBlock* getProgramCodeBlock(JSGlobalData&, ProgramExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+    UnlinkedEvalCodeBlock* getEvalCodeBlock(JSGlobalData&, EvalExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+    UnlinkedFunctionCodeBlock* getFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+    UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(JSGlobalData&, const Identifier&, const SourceCode&, ParserError&);
+    ~CodeCache();
+
+    enum CodeType { EvalType, ProgramType, FunctionType };
+    typedef std::pair<String, unsigned> CodeBlockKey;
+    typedef HashMap<CodeBlockKey, unsigned> CodeBlockIndicesMap;
+    typedef std::pair<String, String> GlobalFunctionKey;
+    typedef HashMap<GlobalFunctionKey, unsigned> GlobalFunctionIndicesMap;
+
+private:
+    CodeCache();
+
+    UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+
+    template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+    CodeBlockKey makeCodeBlockKey(const SourceCode&, CodeType, JSParserStrictness);
+    CodeBlockIndicesMap m_cachedCodeBlockIndices;
+    GlobalFunctionKey makeGlobalFunctionKey(const SourceCode&, const String&);
+    GlobalFunctionIndicesMap m_cachedGlobalFunctionIndices;
+
+    enum {
+        kMaxCodeBlockEntries = 1024,
+        kMaxGlobalFunctionEntries = 1024
+    };
+
+    FixedArray<std::pair<CodeBlockKey, Strong<UnlinkedCodeBlock> >, kMaxCodeBlockEntries> m_cachedCodeBlocks;
+    FixedArray<std::pair<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable> >, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions;
+    WeakRandom m_randomGenerator;
+};
+
+}
+
+#endif
index 0a453eea0566840fe99fbc52d51df0b229c7fbd3..20a2e2acb974624f666c7dbd9d0ff4a4d7a5fae6 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "Executable.h"
 
+#include "BatchedTransitionOptimizer.h"
 #include "BytecodeGenerator.h"
 #include "CodeBlock.h"
 #include "DFGDriver.h"
@@ -133,16 +134,14 @@ void ProgramExecutable::destroy(JSCell* cell)
 
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
 
-FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, FunctionBodyNode* node)
-    : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, node->source(), node->isStrictMode())
-    , m_forceUsesArguments(node->usesArguments())
-    , m_parameters(node->parameters())
-    , m_name(node->ident())
-    , m_inferredName(node->inferredName().isNull() ? globalData.propertyNames->emptyIdentifier : node->inferredName())
-    , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle())
+FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine)
+    : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, unlinkedExecutable->isInStrictContext())
+    , m_unlinkedExecutable(globalData, this, unlinkedExecutable)
 {
-    m_firstLine = node->lineNo();
-    m_lastLine = node->lastLine();
+    ASSERT(!source.isNull());
+    ASSERT(source.length());
+    m_firstLine = firstLine;
+    m_lastLine = lastLine;
 }
 
 void FunctionExecutable::destroy(JSCell* cell)
@@ -191,7 +190,6 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
     UNUSED_PARAM(jitType);
     UNUSED_PARAM(bytecodeIndex);
 #endif
-    JSObject* exception = 0;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     
@@ -200,28 +198,21 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
         m_evalCodeBlock = newCodeBlock.release();
     } else {
+        UNUSED_PARAM(scope);
+        UNUSED_PARAM(globalData);
+        UNUSED_PARAM(lexicalGlobalObject);
         if (!lexicalGlobalObject->evalEnabled())
             return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage()));
-        RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
-        if (!evalNode) {
-            ASSERT(exception);
+
+        JSObject* exception = 0;
+        UnlinkedEvalCodeBlock* unlinkedEvalCode = lexicalGlobalObject->createEvalCodeBlock(exec, this, &exception);
+        if (!unlinkedEvalCode)
             return exception;
-        }
-        recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
-        
-        JSGlobalObject* globalObject = scope->globalObject();
-        
+
         OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
         ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
-        m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
-        OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scope, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get(), !!m_evalCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
-        if ((exception = generator->generate())) {
-            m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative());
-            evalNode->destroyData();
-            return exception;
-        }
-        
-        evalNode->destroyData();
+        m_unlinkedEvalCodeBlock.set(*globalData, this, unlinkedEvalCode);
+        m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
         m_evalCodeBlock->copyPostParseDataFromAlternative();
     }
 
@@ -257,6 +248,7 @@ void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ScriptExecutable::visitChildren(thisObject, visitor);
     if (thisObject->m_evalCodeBlock)
         thisObject->m_evalCodeBlock->visitAggregate(visitor);
+    visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
 }
 
 void EvalExecutable::unlinkCalls()
@@ -272,19 +264,20 @@ void EvalExecutable::unlinkCalls()
 void EvalExecutable::clearCode()
 {
     m_evalCodeBlock.clear();
+    m_unlinkedEvalCodeBlock.clear();
     Base::clearCode();
 }
 
 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
 {
-    JSObject* exception = 0;
+    ParserError error;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+    RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
     if (programNode)
         return 0;
-    ASSERT(exception);
-    return exception;
+    ASSERT(error.m_type != ParserError::ErrorNone);
+    return error.toErrorObject(lexicalGlobalObject, m_source);
 }
 
 JSObject* ProgramExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
@@ -310,38 +303,17 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JI
     SamplingRegion samplingRegion(samplingDescription(jitType));
     
 #if !ENABLE(JIT)
+    UNUSED_PARAM(exec);
     UNUSED_PARAM(jitType);
     UNUSED_PARAM(bytecodeIndex);
 #endif
-    JSObject* exception = 0;
-    JSGlobalData* globalData = &exec->globalData();
-    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    
     if (!!m_programCodeBlock) {
         OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
         m_programCodeBlock = newCodeBlock.release();
     } else {
-        RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
-        if (!programNode) {
-            ASSERT(exception);
-            return exception;
-        }
-        recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
-
         JSGlobalObject* globalObject = scope->globalObject();
-    
-        OwnPtr<CodeBlock> previousCodeBlock = m_programCodeBlock.release();
-        ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
-        m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider(), previousCodeBlock.release()));
-        OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scope, globalObject->symbolTable(), m_programCodeBlock.get(), !!m_programCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
-        if ((exception = generator->generate())) {
-            m_programCodeBlock = static_pointer_cast<ProgramCodeBlock>(m_programCodeBlock->releaseAlternative());
-            programNode->destroyData();
-            return exception;
-        }
-
-        programNode->destroyData();
+        m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), globalObject, source().provider(), m_programCodeBlock.release()));
         m_programCodeBlock->copyPostParseDataFromAlternative();
     }
 
@@ -378,6 +350,67 @@ void ProgramExecutable::unlinkCalls()
 #endif
 }
 
+int ProgramExecutable::addGlobalVar(JSGlobalObject* globalObject, const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
+{
+    // Try to share the symbolTable if possible
+    SharedSymbolTable* symbolTable = globalObject->symbolTable();
+    UNUSED_PARAM(functionMode);
+    int index = symbolTable->size();
+    SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
+    if (functionMode == IsFunctionToSpecialize)
+        newEntry.attemptToWatch();
+    SymbolTable::AddResult result = symbolTable->add(ident.impl(), newEntry);
+    if (!result.isNewEntry) {
+        result.iterator->value.notifyWrite();
+        index = result.iterator->value.getIndex();
+    }
+    return index;
+}
+
+JSObject* ProgramExecutable::initalizeGlobalProperties(JSGlobalData& globalData, CallFrame* callFrame, JSScope* scope)
+{
+    ASSERT(scope);
+    JSGlobalObject* globalObject = scope->globalObject();
+    ASSERT(globalObject);
+    ASSERT(&globalObject->globalData() == &globalData);
+
+    JSObject* exception = 0;
+    UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
+    if (exception)
+        return exception;
+
+    m_unlinkedProgramCodeBlock.set(globalData, this, unlinkedCode);
+
+    BatchedTransitionOptimizer optimizer(globalData, globalObject);
+
+    const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
+    const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
+
+    size_t newGlobals = variableDeclarations.size() + functionDeclarations.size();
+    if (!newGlobals)
+        return 0;
+    globalObject->addRegisters(newGlobals);
+    CallFrame* globalExec = globalObject->globalExec();
+
+    for (size_t i = 0; i < functionDeclarations.size(); ++i) {
+        bool propertyDidExist = globalObject->removeDirect(globalData, functionDeclarations[i].first); // Newly declared functions overwrite existing properties.
+        UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
+        JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(globalData, m_source, lineNo(), 0), scope);
+        int index = addGlobalVar(globalObject, functionDeclarations[i].first, IsVariable,
+            !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
+        globalObject->registerAt(index).set(globalData, globalObject, value);
+    }
+
+    for (size_t i = 0; i < variableDeclarations.size(); ++i) {
+        if (globalObject->hasProperty(globalExec, variableDeclarations[i].first))
+            continue;
+        addGlobalVar(globalObject, variableDeclarations[i].first,
+            (variableDeclarations[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
+            NotFunctionOrNotSpecializable);
+    }
+    return 0;
+}
+
 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
@@ -385,6 +418,7 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
     ScriptExecutable::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
     if (thisObject->m_programCodeBlock)
         thisObject->m_programCodeBlock->visitAggregate(visitor);
 }
@@ -392,6 +426,7 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 void ProgramExecutable::clearCode()
 {
     m_programCodeBlock.clear();
+    m_unlinkedProgramCodeBlock.clear();
     Base::clearCode();
 }
 
@@ -438,12 +473,12 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSSc
 #if ENABLE(JIT)
 bool FunctionExecutable::jitCompileForCall(ExecState* exec)
 {
-    return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
+    return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
 }
 
 bool FunctionExecutable::jitCompileForConstruct(ExecState* exec)
 {
-    return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
+    return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
 }
 #endif
 
@@ -452,49 +487,30 @@ FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializati
     return baselineCodeBlockFor(kind);
 }
 
-PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
+PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
 {
     if (!!codeBlockFor(specializationKind))
         return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
-    
-    exception = 0;
+
     JSGlobalData* globalData = scope->globalData();
     JSGlobalObject* globalObject = scope->globalObject();
-    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(
-        globalData,
-        globalObject,
-        m_source,
-        m_parameters.get(),
-        name(),
-        isStrictMode() ? JSParseStrict : JSParseNormal,
-        FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode,
-        0,
-        0,
-        &exception
-    );
-
-    if (!body) {
-        ASSERT(exception);
+    ParserError error;
+    DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
+    ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
+    UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*globalData, m_source, specializationKind, debuggerMode, profilerMode, error);
+    recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine());
+
+    if (!unlinkedCodeBlock) {
+        exception = error.toErrorObject(globalObject, m_source);
         return nullptr;
     }
-    if (m_forceUsesArguments)
-        body->setUsesArguments();
-    body->finishParsing(m_parameters, m_name, m_functionNameIsInScopeToggle);
-    recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
-
-    OwnPtr<FunctionCodeBlock> result;
-    ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind));
-    result = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), specializationKind == CodeForConstruct));
-    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scope, result->symbolTable(), result.get(), compilationKind)));
-    exception = generator->generate();
-    body->destroyData();
-    if (exception)
-        return nullptr;
 
+    OwnPtr<FunctionCodeBlock> result = adoptPtr(new FunctionCodeBlock(this, unlinkedCodeBlock, globalObject, source().provider(), source().startOffset()));
     result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
     return result.release();
 }
 
+
 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
 {
     SamplingRegion samplingRegion(samplingDescription(jitType));
@@ -507,7 +523,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s
 #endif
     ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
     JSObject* exception;
-    OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, !!m_codeBlockForCall ? OptimizingCompilation : FirstCompilation, CodeForCall, exception);
+    OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForCall, exception);
     if (!newCodeBlock)
         return exception;
 
@@ -516,10 +532,9 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s
     
     m_numParametersForCall = m_codeBlockForCall->numParameters();
     ASSERT(m_numParametersForCall);
-    m_symbolTable.set(exec->globalData(), this, m_codeBlockForCall->symbolTable());
 
 #if ENABLE(JIT)
-    if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, bytecodeIndex, CodeForCall))
+    if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, jitType, bytecodeIndex, CodeForCall))
         return 0;
 #endif
 
@@ -544,7 +559,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco
     
     ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
     JSObject* exception;
-    OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, !!m_codeBlockForConstruct ? OptimizingCompilation : FirstCompilation, CodeForConstruct, exception);
+    OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForConstruct, exception);
     if (!newCodeBlock)
         return exception;
 
@@ -553,10 +568,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco
     
     m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
     ASSERT(m_numParametersForConstruct);
-    m_symbolTable.set(exec->globalData(), this, m_codeBlockForConstruct->symbolTable());
 
 #if ENABLE(JIT)
-    if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, bytecodeIndex, CodeForConstruct))
+    if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, jitType, bytecodeIndex, CodeForConstruct))
         return 0;
 #endif
 
@@ -592,12 +606,11 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
     ScriptExecutable::visitChildren(thisObject, visitor);
-    visitor.append(&thisObject->m_nameValue);
-    visitor.append(&thisObject->m_symbolTable);
     if (thisObject->m_codeBlockForCall)
         thisObject->m_codeBlockForCall->visitAggregate(visitor);
     if (thisObject->m_codeBlockForConstruct)
         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
+    visitor.append(&thisObject->m_unlinkedExecutable);
 }
 
 void FunctionExecutable::clearCodeIfNotCompiling()
@@ -607,10 +620,18 @@ void FunctionExecutable::clearCodeIfNotCompiling()
     clearCode();
 }
 
+void FunctionExecutable::clearUnlinkedCodeIfNotCompiling()
+{
+    if (isCompiling())
+        return;
+    m_unlinkedExecutable->clearCode();
+}
+
 void FunctionExecutable::clearCode()
 {
     m_codeBlockForCall.clear();
     m_codeBlockForConstruct.clear();
+    m_unlinkedExecutable->clearCode();
     Base::clearCode();
 }
 
@@ -630,39 +651,19 @@ void FunctionExecutable::unlinkCalls()
 
 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
 {
-    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
-    if (!program) {
-        ASSERT(*exception);
+    UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
+    if (!unlinkedFunction)
         return 0;
-    }
-
-    // This function assumes an input string that would result in a single anonymous function expression.
-    StatementNode* exprStatement = program->singleStatement();
-    ASSERT(exprStatement);
-    ASSERT(exprStatement->isExprStatement());
-    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
-    ASSERT(funcExpr);
-    ASSERT(funcExpr->isFuncExprNode());
-    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
-    ASSERT(body);
-    ASSERT(body->ident().isNull());
-
-    FunctionExecutable* functionExecutable = FunctionExecutable::create(exec->globalData(), body);
-    functionExecutable->m_nameValue.set(exec->globalData(), functionExecutable, jsString(&exec->globalData(), name.string()));
-    return functionExecutable;
+    unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
+    unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
+    unsigned sourceLength = unlinkedFunction->sourceLength();
+    SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine);
+    return FunctionExecutable::create(exec->globalData(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount());
 }
 
 String FunctionExecutable::paramString() const
 {
-    FunctionParameters& parameters = *m_parameters;
-    StringBuilder builder;
-    for (size_t pos = 0; pos < parameters.size(); ++pos) {
-        if (!builder.isEmpty())
-            builder.appendLiteral(", ");
-        builder.append(parameters[pos].string());
-    }
-    return builder.toString();
+    return m_unlinkedExecutable->paramString();
 }
 
 }
index 76a537da324aac9203cd84d091cc8c932f2ff036..74b4add75c32f386d44cae2488b1924de2c80c75 100644 (file)
@@ -35,6 +35,7 @@
 #include "LLIntCLoop.h"
 #include "Nodes.h"
 #include "SamplingTool.h"
+#include "UnlinkedCodeBlock.h"
 #include <wtf/PassOwnPtr.h>
 
 namespace JSC {
@@ -364,9 +365,19 @@ namespace JSC {
         bool isStrictMode() const { return m_features & StrictModeFeature; }
 
         void unlinkCalls();
+
+        CodeFeatures features() const { return m_features; }
         
         static const ClassInfo s_info;
 
+        void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+        {
+            m_features = features;
+            m_hasCapturedVariables = hasCapturedVariables;
+            m_firstLine = firstLine;
+            m_lastLine = lastLine;
+        }
+
     protected:
         void finishCreation(JSGlobalData& globalData)
         {
@@ -379,14 +390,6 @@ namespace JSC {
 #endif
         }
 
-        void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
-        {
-            m_features = features;
-            m_hasCapturedVariables = hasCapturedVariables;
-            m_firstLine = firstLine;
-            m_lastLine = lastLine;
-        }
-
         SourceCode m_source;
         CodeFeatures m_features;
         bool m_hasCapturedVariables;
@@ -448,6 +451,8 @@ namespace JSC {
 
         void clearCode();
 
+        ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         EvalExecutable(ExecState*, const SourceCode&, bool);
@@ -456,6 +461,7 @@ namespace JSC {
         static void visitChildren(JSCell*, SlotVisitor&);
 
         OwnPtr<EvalCodeBlock> m_evalCodeBlock;
+        WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
     };
 
     class ProgramExecutable : public ScriptExecutable {
@@ -470,6 +476,9 @@ namespace JSC {
             return executable;
         }
 
+
+        JSObject* initalizeGlobalProperties(JSGlobalData&, CallFrame*, JSScope*);
+
         static void destroy(JSCell*);
 
         JSObject* compile(ExecState* exec, JSScope* scope)
@@ -515,13 +524,21 @@ namespace JSC {
 
         void clearCode();
 
+        ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
+
         ProgramExecutable(ExecState*, const SourceCode&);
 
+        enum ConstantMode { IsConstant, IsVariable };
+        enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
+        int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
+
         JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
         static void visitChildren(JSCell*, SlotVisitor&);
 
+        WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
 
@@ -531,9 +548,9 @@ namespace JSC {
     public:
         typedef ScriptExecutable Base;
 
-        static FunctionExecutable* create(JSGlobalData& globalData, FunctionBodyNode* node)
+        static FunctionExecutable* create(JSGlobalData& globalData, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine)
         {
-            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, node);
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, source, unlinkedExecutable, firstLine, lastLine);
             executable->finishCreation(globalData);
             return executable;
         }
@@ -554,7 +571,7 @@ namespace JSC {
         
         FunctionCodeBlock* codeBlockWithBytecodeFor(CodeSpecializationKind);
         
-        PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CompilationKind, CodeSpecializationKind, JSObject*& exception);
+        PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
 
         JSObject* compileForCall(ExecState* exec, JSScope* scope)
         {
@@ -679,14 +696,15 @@ namespace JSC {
             return baselineCodeBlockFor(kind);
         }
         
-        const Identifier& name() { return m_name; }
-        const Identifier& inferredName() { return m_inferredName; }
-        JSString* nameValue() const { return m_nameValue.get(); }
-        size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'!
+        const Identifier& name() { return m_unlinkedExecutable->name(); }
+        const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
+        JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
+        size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
         String paramString() const;
-        SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
+        SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
 
         void clearCodeIfNotCompiling();
+        void clearUnlinkedCodeIfNotCompiling();
         static void visitChildren(JSCell*, SlotVisitor&);
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
@@ -699,15 +717,8 @@ namespace JSC {
 
         void clearCode();
 
-    protected:
-        void finishCreation(JSGlobalData& globalData)
-        {
-            Base::finishCreation(globalData);
-            m_nameValue.set(globalData, this, jsString(&globalData, name().string()));
-        }
-
     private:
-        FunctionExecutable(JSGlobalData&, FunctionBodyNode*);
+        FunctionExecutable(JSGlobalData&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine);
 
         JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
         JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
@@ -732,16 +743,9 @@ namespace JSC {
         }
 
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
-        bool m_forceUsesArguments;
-
-        RefPtr<FunctionParameters> m_parameters;
+        WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
         OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
         OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
-        Identifier m_name;
-        Identifier m_inferredName;
-        FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
-        WriteBarrier<JSString> m_nameValue;
-        WriteBarrier<SharedSymbolTable> m_symbolTable;
     };
 
     inline JSFunction::JSFunction(JSGlobalData& globalData, FunctionExecutable* executable, JSScope* scope)
index 065788aee1be25f30df65bc99a131058ee19c656..b71b60217fa5e4c314414a990e610c9f5946c18b 100644 (file)
@@ -49,7 +49,7 @@ inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBloc
     return jitCompileIfAppropriate(exec, codeBlock, jitCode, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
 }
 
-inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, WriteBarrier<SharedSymbolTable>& symbolTable, JITCode::JITType jitType, unsigned bytecodeIndex, CodeSpecializationKind kind)
+inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType, unsigned bytecodeIndex, CodeSpecializationKind kind)
 {
 #if ENABLE(LLINT)
     if (JITCode::isBaselineCode(jitType)) {
@@ -61,7 +61,7 @@ inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBloc
 #else
     UNUSED_PARAM(kind);
 #endif // ENABLE(LLINT)
-    return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
+    return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
 }
 
 } // namespace JSC
index fa2291813f9baabe0d6f0c69be67784cd434d11d..fc633646316858bdf69dfdf41b2a720b8c014ebd 100644 (file)
@@ -46,15 +46,16 @@ namespace JSC {
     public:
         typedef JSVariableObject Base;
 
-        static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* functionExecutable)
+        static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, CodeBlock* codeBlock)
         {
+            SharedSymbolTable* symbolTable = codeBlock->symbolTable();
             JSActivation* activation = new (
                 NotNull,
                 allocateCell<JSActivation>(
                     globalData.heap,
-                    allocationSize(functionExecutable->symbolTable())
+                    allocationSize(symbolTable)
                 )
-            ) JSActivation(globalData, callFrame, functionExecutable->symbolTable());
+            ) JSActivation(globalData, callFrame, symbolTable);
             activation->finishCreation(globalData);
             return activation;
         }
index 12a28e341fb02ab98732fe20d5e63565884a01ed..4dca5b0f6fe7aa15f70b8914a6e362a590df975b 100644 (file)
@@ -30,6 +30,7 @@
 #include "JSGlobalData.h"
 
 #include "ArgList.h"
+#include "CodeCache.h"
 #include "CommonIdentifiers.h"
 #include "DebuggerActivation.h"
 #include "FunctionConstructor.h"
@@ -57,6 +58,7 @@
 #include "RegExpObject.h"
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
+#include "UnlinkedCodeBlock.h"
 #include <wtf/RetainPtr.h>
 #include <wtf/Threading.h>
 #include <wtf/WTFThreadData.h>
@@ -196,6 +198,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
     , m_initializingObjectClass(0)
 #endif
     , m_inDefineOwnProperty(false)
+    , m_codeCache(CodeCache::create())
 {
     interpreter = new Interpreter(*this);
 
@@ -221,6 +224,11 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
     sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull()));
     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
     sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
+    withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull()));
+    unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull()));
+    unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
+    unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
+    unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
 
     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
 
index e97c0a015d4854454707773f17166e2006c043de..0ffaccb6ad125f764f4b5d5b1297eec53a26a9d9 100644 (file)
@@ -63,6 +63,7 @@ struct OpaqueJSClassContextData;
 namespace JSC {
 
     class CodeBlock;
+    class CodeCache;
     class CommonIdentifiers;
     class HandleStack;
     class IdentifierTable;
@@ -80,6 +81,10 @@ namespace JSC {
 #if ENABLE(REGEXP_TRACING)
     class RegExp;
 #endif
+    class UnlinkedCodeBlock;
+    class UnlinkedEvalCodeBlock;
+    class UnlinkedFunctionExecutable;
+    class UnlinkedProgramCodeBlock;
 
     struct HashTable;
     struct Instruction;
@@ -223,6 +228,11 @@ namespace JSC {
         Strong<Structure> sharedSymbolTableStructure;
         Strong<Structure> structureChainStructure;
         Strong<Structure> sparseArrayValueMapStructure;
+        Strong<Structure> withScopeStructure;
+        Strong<Structure> unlinkedFunctionExecutableStructure;
+        Strong<Structure> unlinkedProgramCodeBlockStructure;
+        Strong<Structure> unlinkedEvalCodeBlockStructure;
+        Strong<Structure> unlinkedFunctionCodeBlockStructure;
 
         IdentifierTable* identifierTable;
         CommonIdentifiers* propertyNames;
@@ -436,6 +446,7 @@ namespace JSC {
         }
 
         JSLock& apiLock() { return m_apiLock; }
+        CodeCache* codeCache() { return m_codeCache.get(); }
 
     private:
         friend class LLIntOffsetsExtractor;
@@ -456,6 +467,7 @@ namespace JSC {
         const ClassInfo* m_initializingObjectClass;
 #endif
         bool m_inDefineOwnProperty;
+        OwnPtr<CodeCache> m_codeCache;
 
         TypedArrayDescriptor m_int8ArrayDescriptor;
         TypedArrayDescriptor m_int16ArrayDescriptor;
index 03252fad1ca71284c6a0cc20dbe617aec7787bcb..c466a2b04a2d61ea389c11ba72fb5cbf9c4b80bc 100644 (file)
@@ -36,6 +36,7 @@
 #include "BooleanConstructor.h"
 #include "BooleanPrototype.h"
 #include "CodeBlock.h"
+#include "CodeCache.h"
 #include "DateConstructor.h"
 #include "DatePrototype.h"
 #include "Debugger.h"
@@ -580,4 +581,58 @@ void slowValidateCell(JSGlobalObject* globalObject)
     ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info);
 }
 
+UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* callFrame, ProgramExecutable* executable, JSObject** exception)
+{
+    ParserError error;
+    JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
+    DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
+    ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
+    UnlinkedProgramCodeBlock* unlinkedCode = globalData().codeCache()->getProgramCodeBlock(globalData(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+
+    if (hasDebugger())
+        debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
+
+    if (error.m_type != ParserError::ErrorNone) {
+        *exception = error.toErrorObject(this, executable->source());
+        return 0;
+    }
+    
+    return unlinkedCode;
+}
+
+UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame, EvalExecutable* executable, JSObject** exception)
+{
+    ParserError error;
+    JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
+    DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
+    ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
+    UnlinkedEvalCodeBlock* unlinkedCode = globalData().codeCache()->getEvalCodeBlock(globalData(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+
+    if (hasDebugger())
+        debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
+
+    if (error.m_type != ParserError::ErrorNone) {
+        *exception = error.toErrorObject(this, executable->source());
+        return 0;
+    }
+
+    return unlinkedCode;
+}
+
+UnlinkedFunctionExecutable* JSGlobalObject::createFunctionExecutableFromGlobalCode(CallFrame* callFrame, const Identifier& name, const SourceCode& code, JSObject** exception)
+{
+    ParserError error;
+    UnlinkedFunctionExecutable* executable = globalData().codeCache()->getFunctionExecutableFromGlobalCode(globalData(), name, code, error);
+    if (hasDebugger())
+        debugger()->sourceParsed(callFrame, code.provider(), error.m_line, error.m_message);
+
+    if (error.m_type != ParserError::ErrorNone) {
+        *exception = error.toErrorObject(this, code);
+        return 0;
+    }
+
+    return executable;
+}
+
+
 } // namespace JSC
index 65fda49d84884820223268f5a3b1a55055fe7d22..3212363ab4e713afb4a1642993c03564447ffad7 100644 (file)
@@ -43,6 +43,10 @@ namespace JSC {
     class Debugger;
     class ErrorConstructor;
     class ErrorPrototype;
+    class EvalCodeBlock;
+    class EvalExecutable;
+    class FunctionCodeBlock;
+    class FunctionExecutable;
     class FunctionPrototype;
     class GetterSetter;
     class GlobalCodeBlock;
@@ -50,9 +54,10 @@ namespace JSC {
     class LLIntOffsetsExtractor;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
+    class ProgramExecutable;
     class RegExpConstructor;
     class RegExpPrototype;
-
+    class SourceCode;
     struct ActivationStackNode;
     struct HashTable;
 
@@ -185,6 +190,9 @@ namespace JSC {
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
+        bool hasDebugger() const { return m_debugger; }
+        bool hasProfiler() const { return globalObjectMethodTable()->supportsProfiling(this); }
+
     protected:
         JS_EXPORT_PRIVATE explicit JSGlobalObject(JSGlobalData&, Structure*, const GlobalObjectMethodTable* = 0);
 
@@ -366,6 +374,11 @@ namespace JSC {
 
         double weakRandomNumber() { return m_weakRandom.get(); }
         unsigned weakRandomInteger() { return m_weakRandom.getUint32(); }
+
+        UnlinkedProgramCodeBlock* createProgramCodeBlock(CallFrame*, ProgramExecutable*, JSObject** exception);
+        UnlinkedEvalCodeBlock* createEvalCodeBlock(CallFrame*, EvalExecutable*, JSObject** exception);
+        UnlinkedFunctionExecutable* createFunctionExecutableFromGlobalCode(CallFrame*, const Identifier&, const SourceCode&, JSObject** exception);
+
     protected:
 
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
index 03f4a77909077e6a6c5daa38b5b329e0061c628b..10d98d2bd25a6d1e22747b7003a8160d831b316b 100644 (file)
@@ -41,6 +41,11 @@ enum JSType {
     ProgramExecutableType,
     FunctionExecutableType,
 
+    UnlinkedFunctionExecutableType,
+    UnlinkedProgramCodeBlockType,
+    UnlinkedEvalCodeBlockType,
+    UnlinkedFunctionCodeBlockType,
+
     // The ObjectType value must come before any JSType that is a subclass of JSObject.
     ObjectType,
     FinalObjectType,