Remove AST nodes from use within the Runtime (outside of parsing), stage 1
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Aug 2009 01:14:00 +0000 (01:14 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Aug 2009 01:14:00 +0000 (01:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=28330

Reviewed by Oliver Hunt.

Remove the EvalNode and ProgramNode from use in the runtime.  They still exist
after this patch, but are hidden behind EvalExecutable and FunctionExecutable,
and are also still reachable behind CodeBlock::m_ownerNode.

The next step will be to beat back FunctionBodyNode in the same fashion.
Then remove the usage via CodeBlock, then only construct these nodes only on
demand during bytecode generation.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
(JSC::GlobalCodeBlock::GlobalCodeBlock):
(JSC::GlobalCodeBlock::~GlobalCodeBlock):
(JSC::ProgramCodeBlock::ProgramCodeBlock):
(JSC::EvalCodeBlock::EvalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):
(JSC::NativeCodeBlock::NativeCodeBlock):
* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::get):
* debugger/Debugger.cpp:
(JSC::evaluateInGlobalCallFrame):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::evaluate):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::callEval):
(JSC::Interpreter::execute):
* interpreter/Interpreter.h:
* parser/Nodes.cpp:
(JSC::FunctionBodyNode::createNativeThunk):
(JSC::FunctionBodyNode::generateBytecode):
(JSC::FunctionBodyNode::bytecodeForExceptionInfoReparse):
* parser/Parser.h:
(JSC::Parser::parse):
(JSC::Parser::reparse):
(JSC::Parser::parseFunctionFromGlobalCode):
(JSC::::parse):
* runtime/Completion.cpp:
(JSC::checkSyntax):
(JSC::evaluate):
* runtime/Error.cpp:
(JSC::throwError):
* runtime/Error.h:
* runtime/Executable.h: Added.
(JSC::TemplateExecutable::TemplateExecutable):
(JSC::TemplateExecutable::markAggregate):
(JSC::TemplateExecutable::sourceURL):
(JSC::TemplateExecutable::lineNo):
(JSC::TemplateExecutable::bytecode):
(JSC::TemplateExecutable::jitCode):
(JSC::EvalExecutable::EvalExecutable):
(JSC::ProgramExecutable::ProgramExecutable):
* runtime/FunctionConstructor.cpp:
(JSC::constructFunction):
* runtime/FunctionConstructor.h:
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::numericCompareFunction):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::~JSGlobalObject):
(JSC::JSGlobalObject::markChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::codeBlocks):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):

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

20 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/bytecode/CodeBlock.h
JavaScriptCore/bytecode/EvalCodeCache.h
JavaScriptCore/debugger/Debugger.cpp
JavaScriptCore/debugger/DebuggerCallFrame.cpp
JavaScriptCore/interpreter/Interpreter.cpp
JavaScriptCore/interpreter/Interpreter.h
JavaScriptCore/parser/Nodes.cpp
JavaScriptCore/parser/Parser.h
JavaScriptCore/runtime/Completion.cpp
JavaScriptCore/runtime/Error.cpp
JavaScriptCore/runtime/Error.h
JavaScriptCore/runtime/Executable.h [new file with mode: 0644]
JavaScriptCore/runtime/FunctionConstructor.cpp
JavaScriptCore/runtime/FunctionConstructor.h
JavaScriptCore/runtime/JSGlobalData.cpp
JavaScriptCore/runtime/JSGlobalObject.cpp
JavaScriptCore/runtime/JSGlobalObject.h
JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

index a7673f7..b9da140 100644 (file)
@@ -1,3 +1,73 @@
+2009-08-14  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Remove AST nodes from use within the Runtime (outside of parsing), stage 1
+        https://bugs.webkit.org/show_bug.cgi?id=28330
+
+        Remove the EvalNode and ProgramNode from use in the runtime.  They still exist
+        after this patch, but are hidden behind EvalExecutable and FunctionExecutable,
+        and are also still reachable behind CodeBlock::m_ownerNode.
+
+        The next step will be to beat back FunctionBodyNode in the same fashion.
+        Then remove the usage via CodeBlock, then only construct these nodes only on
+        demand during bytecode generation.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.h:
+        (JSC::GlobalCodeBlock::GlobalCodeBlock):
+        (JSC::GlobalCodeBlock::~GlobalCodeBlock):
+        (JSC::ProgramCodeBlock::ProgramCodeBlock):
+        (JSC::EvalCodeBlock::EvalCodeBlock):
+        (JSC::FunctionCodeBlock::FunctionCodeBlock):
+        (JSC::NativeCodeBlock::NativeCodeBlock):
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::get):
+        * debugger/Debugger.cpp:
+        (JSC::evaluateInGlobalCallFrame):
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::evaluate):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::callEval):
+        (JSC::Interpreter::execute):
+        * interpreter/Interpreter.h:
+        * parser/Nodes.cpp:
+        (JSC::FunctionBodyNode::createNativeThunk):
+        (JSC::FunctionBodyNode::generateBytecode):
+        (JSC::FunctionBodyNode::bytecodeForExceptionInfoReparse):
+        * parser/Parser.h:
+        (JSC::Parser::parse):
+        (JSC::Parser::reparse):
+        (JSC::Parser::parseFunctionFromGlobalCode):
+        (JSC::::parse):
+        * runtime/Completion.cpp:
+        (JSC::checkSyntax):
+        (JSC::evaluate):
+        * runtime/Error.cpp:
+        (JSC::throwError):
+        * runtime/Error.h:
+        * runtime/Executable.h: Added.
+        (JSC::TemplateExecutable::TemplateExecutable):
+        (JSC::TemplateExecutable::markAggregate):
+        (JSC::TemplateExecutable::sourceURL):
+        (JSC::TemplateExecutable::lineNo):
+        (JSC::TemplateExecutable::bytecode):
+        (JSC::TemplateExecutable::jitCode):
+        (JSC::EvalExecutable::EvalExecutable):
+        (JSC::ProgramExecutable::ProgramExecutable):
+        * runtime/FunctionConstructor.cpp:
+        (JSC::constructFunction):
+        * runtime/FunctionConstructor.h:
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::numericCompareFunction):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::~JSGlobalObject):
+        (JSC::JSGlobalObject::markChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::codeBlocks):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncEval):
+
 2009-08-14  Darin Adler  <darin@apple.com>
 
         Reviewed by Sam Weinig.
 2009-08-14  Darin Adler  <darin@apple.com>
 
         Reviewed by Sam Weinig.
index 24264c2..740b034 100644 (file)
                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; };
                86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; };
                86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; };
                86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; };
                86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
+               86CAFEE31035DDE60028A609 /* Executable.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CAFEE21035DDE60028A609 /* Executable.h */; settings = {ATTRIBUTES = (Private, ); }; };
                86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CC85A00EE79A4700288682 /* JITInlineMethods.h */; };
                86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85A20EE79B7400288682 /* JITCall.cpp */; };
                86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */; };
                86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CC85A00EE79A4700288682 /* JITInlineMethods.h */; };
                86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85A20EE79B7400288682 /* JITCall.cpp */; };
                86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */; };
                86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; };
                86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; };
                86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; };
                86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; };
                86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; };
                86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; };
+               86CAFEE21035DDE60028A609 /* Executable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Executable.h; sourceTree = "<group>"; };
                86CC85A00EE79A4700288682 /* JITInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITInlineMethods.h; sourceTree = "<group>"; };
                86CC85A20EE79B7400288682 /* JITCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITCall.cpp; sourceTree = "<group>"; };
                86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITPropertyAccess.cpp; sourceTree = "<group>"; };
                86CC85A00EE79A4700288682 /* JITInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITInlineMethods.h; sourceTree = "<group>"; };
                86CC85A20EE79B7400288682 /* JITCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITCall.cpp; sourceTree = "<group>"; };
                86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITPropertyAccess.cpp; sourceTree = "<group>"; };
                                BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
                                1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
                                A72701B30DADE94900E548D7 /* ExceptionHelpers.h */,
                                BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
                                1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
                                A72701B30DADE94900E548D7 /* ExceptionHelpers.h */,
+                               86CAFEE21035DDE60028A609 /* Executable.h */,
                                BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */,
                                BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */,
                                F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
                                BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */,
                                BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */,
                                F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
                                9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
                                A7795590101A74D500114E55 /* MarkStack.h in Headers */,
                                A7D649AA1015224E009B2E1B /* PossiblyNull.h in Headers */,
                                9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
                                A7795590101A74D500114E55 /* MarkStack.h in Headers */,
                                A7D649AA1015224E009B2E1B /* PossiblyNull.h in Headers */,
+                               86CAFEE31035DDE60028A609 /* Executable.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 5d1b304..0487918 100644 (file)
@@ -250,9 +250,10 @@ namespace JSC {
 
     class CodeBlock : public FastAllocBase {
         friend class JIT;
 
     class CodeBlock : public FastAllocBase {
         friend class JIT;
-    public:
+    protected:
         CodeBlock(ScopeNode* ownerNode);
         CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
         CodeBlock(ScopeNode* ownerNode);
         CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
+    public:
         ~CodeBlock();
 
         void markAggregate(MarkStack&);
         ~CodeBlock();
 
         void markAggregate(MarkStack&);
@@ -550,16 +551,16 @@ namespace JSC {
     // Program code is not marked by any function, so we make the global object
     // responsible for marking it.
 
     // Program code is not marked by any function, so we make the global object
     // responsible for marking it.
 
-    class ProgramCodeBlock : public CodeBlock {
+    class GlobalCodeBlock : public CodeBlock {
     public:
     public:
-        ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
-            : CodeBlock(ownerNode, codeType, sourceProvider, 0)
+        GlobalCodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, JSGlobalObject* globalObject)
+            : CodeBlock(ownerNode, codeType, sourceProvider, sourceOffset)
             , m_globalObject(globalObject)
         {
             m_globalObject->codeBlocks().add(this);
         }
 
             , m_globalObject(globalObject)
         {
             m_globalObject->codeBlocks().add(this);
         }
 
-        ~ProgramCodeBlock()
+        ~GlobalCodeBlock()
         {
             if (m_globalObject)
                 m_globalObject->codeBlocks().remove(this);
         {
             if (m_globalObject)
                 m_globalObject->codeBlocks().remove(this);
@@ -571,10 +572,18 @@ namespace JSC {
         JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
     };
 
         JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
     };
 
-    class EvalCodeBlock : public ProgramCodeBlock {
+    class ProgramCodeBlock : public GlobalCodeBlock {
+    public:
+        ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
+            : GlobalCodeBlock(ownerNode, codeType, sourceProvider, 0, globalObject)
+        {
+        }
+    };
+
+    class EvalCodeBlock : public GlobalCodeBlock {
     public:
         EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
     public:
         EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
-            : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
+            : GlobalCodeBlock(ownerNode, EvalCode, sourceProvider, 0, globalObject)
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
@@ -585,6 +594,22 @@ namespace JSC {
         int m_baseScopeDepth;
     };
 
         int m_baseScopeDepth;
     };
 
+    class FunctionCodeBlock : public CodeBlock {
+    public:
+        FunctionCodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
+            : CodeBlock(ownerNode, codeType, sourceProvider, sourceOffset)
+        {
+        }
+    };
+
+    class NativeCodeBlock : public CodeBlock {
+    public:
+        NativeCodeBlock(ScopeNode* ownerNode)
+            : CodeBlock(ownerNode)
+        {
+        }
+    };
+
     inline Register& ExecState::r(int index)
     {
         CodeBlock* codeBlock = this->codeBlock();
     inline Register& ExecState::r(int index)
     {
         CodeBlock* codeBlock = this->codeBlock();
index 986525c..6506c0c 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef EvalCodeCache_h
 #define EvalCodeCache_h
 
 #ifndef EvalCodeCache_h
 #define EvalCodeCache_h
 
+#include "Executable.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "Parser.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "Parser.h"
@@ -41,29 +42,24 @@ namespace JSC {
 
     class EvalCodeCache {
     public:
 
     class EvalCodeCache {
     public:
-        PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        PassRefPtr<EvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
         {
         {
-            RefPtr<EvalNode> evalNode;
+            RefPtr<EvalExecutable> evalExecutable;
 
             if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
 
             if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
-                evalNode = m_cacheMap.get(evalSource.rep());
+                evalExecutable = m_cacheMap.get(evalSource.rep());
 
 
-            if (!evalNode) {
-                int errorLine;
-                UString errorMessage;
-                
-                SourceCode source = makeSource(evalSource);
-                evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage);
-                if (evalNode) {
-                    if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
-                        m_cacheMap.set(evalSource.rep(), evalNode);
-                } else {
-                    exceptionValue = Error::create(exec, SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0);
+            if (!evalExecutable) {
+                evalExecutable = new EvalExecutable(makeSource(evalSource));
+                exceptionValue = evalExecutable->parse(exec);
+                if (exceptionValue)
                     return 0;
                     return 0;
-                }
+
+                if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
+                    m_cacheMap.set(evalSource.rep(), evalExecutable);
             }
 
             }
 
-            return evalNode.release();
+            return evalExecutable.release();
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
@@ -78,7 +74,7 @@ namespace JSC {
         static const int maxCacheableSourceLength = 256;
         static const int maxCacheEntries = 64;
 
         static const int maxCacheableSourceLength = 256;
         static const int maxCacheEntries = 64;
 
-        typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > EvalCacheMap;
+        typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalExecutable> > EvalCacheMap;
         EvalCacheMap m_cacheMap;
     };
 
         EvalCacheMap m_cacheMap;
     };
 
index 2a08fec..c9d59f7 100644 (file)
@@ -113,14 +113,12 @@ JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSG
 {
     CallFrame* globalCallFrame = globalObject->globalExec();
 
 {
     CallFrame* globalCallFrame = globalObject->globalExec();
 
-    int errLine;
-    UString errMsg;
-    SourceCode source = makeSource(script);
-    RefPtr<EvalNode> evalNode = globalObject->globalData()->parser->parse<EvalNode>(globalCallFrame, globalObject->debugger(), source, &errLine, &errMsg);
-    if (!evalNode)
-        return Error::create(globalCallFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
-
-    return globalObject->globalData()->interpreter->execute(evalNode.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
+    EvalExecutable eval(makeSource(script));
+    JSObject* error = eval.parse(globalCallFrame);
+    if (error)
+        return error;
+
+    return globalObject->globalData()->interpreter->execute(&eval, globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index e90525c..f2afba6 100644 (file)
@@ -79,14 +79,12 @@ JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) c
     if (!m_callFrame->codeBlock())
         return JSValue();
 
     if (!m_callFrame->codeBlock())
         return JSValue();
 
-    int errLine;
-    UString errMsg;
-    SourceCode source = makeSource(script);
-    RefPtr<EvalNode> evalNode = m_callFrame->scopeChain()->globalData->parser->parse<EvalNode>(m_callFrame, m_callFrame->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-    if (!evalNode)
-        return Error::create(m_callFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+    EvalExecutable eval(makeSource(script));
+    JSObject* error = eval.parse(m_callFrame);
+    if (error)
+        return error;
 
 
-    return m_callFrame->scopeChain()->globalData->interpreter->execute(evalNode.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
+    return m_callFrame->scopeChain()->globalData->interpreter->execute(&eval, m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 37ecf76..c1ce054 100644 (file)
@@ -354,11 +354,11 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r
     
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     CodeBlock* codeBlock = callFrame->codeBlock();
     
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     CodeBlock* codeBlock = callFrame->codeBlock();
-    RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
+    RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
 
     JSValue result = jsUndefined();
 
     JSValue result = jsUndefined();
-    if (evalNode)
-        result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
+    if (eval)
+        result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
 
     return result;
 }
 
     return result;
 }
@@ -610,7 +610,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
     return handler;
 }
 
     return handler;
 }
 
-JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
+JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
 {
     ASSERT(!scopeChain->globalData->exception);
 
 {
     ASSERT(!scopeChain->globalData->exception);
 
@@ -621,7 +621,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
         }
     }
 
         }
     }
 
-    CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
+    CodeBlock* codeBlock = &program->bytecode(scopeChain);
 
     Register* oldEnd = m_registerFile.end();
     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
 
     Register* oldEnd = m_registerFile.end();
     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
@@ -645,7 +645,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
+        (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo());
 
     JSValue result;
     {
 
     JSValue result;
     {
@@ -653,7 +653,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
 
         m_reentryDepth++;
 #if ENABLE(JIT)
 
         m_reentryDepth++;
 #if ENABLE(JIT)
-        result = programNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+        result = program->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
@@ -661,7 +661,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
     }
 
     if (*profiler)
     }
 
     if (*profiler)
-        (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo());
+        (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
 
     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
         lastGlobalObject->copyGlobalsTo(m_registerFile);
 
     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
         lastGlobalObject->copyGlobalsTo(m_registerFile);
@@ -804,12 +804,12 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure)
     m_registerFile.shrink(closure.oldEnd);
 }
 
     m_registerFile.shrink(closure.oldEnd);
 }
 
-JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
 {
 {
-    return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
+    return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
 }
 
 }
 
-JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
 {
     ASSERT(!scopeChain->globalData->exception);
 
 {
     ASSERT(!scopeChain->globalData->exception);
 
@@ -822,7 +822,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
 
     DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
 
 
     DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
 
-    EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain);
+    EvalCodeBlock* codeBlock = &eval->bytecode(scopeChain);
 
     JSVariableObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
 
     JSVariableObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
@@ -874,7 +874,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
+        (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo());
 
     JSValue result;
     {
 
     JSValue result;
     {
@@ -882,7 +882,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
 
         m_reentryDepth++;
 #if ENABLE(JIT)
 
         m_reentryDepth++;
 #if ENABLE(JIT)
-        result = evalNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+        result = eval->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
@@ -890,7 +890,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
     }
 
     if (*profiler)
     }
 
     if (*profiler)
-        (*profiler)->didExecute(callFrame, evalNode->sourceURL(), evalNode->lineNo());
+        (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
 
     m_registerFile.shrink(oldEnd);
     return result;
 
     m_registerFile.shrink(oldEnd);
     return result;
index 519c508..9a50552 100644 (file)
 namespace JSC {
 
     class CodeBlock;
 namespace JSC {
 
     class CodeBlock;
-    class EvalNode;
+    class EvalExecutable;
     class FunctionBodyNode;
     class InternalFunction;
     class JSFunction;
     class JSGlobalObject;
     class FunctionBodyNode;
     class InternalFunction;
     class JSFunction;
     class JSGlobalObject;
-    class ProgramNode;
+    class ProgramExecutable;
     class Register;
     class ScopeChainNode;
     class SamplingTool;
     class Register;
     class ScopeChainNode;
     class SamplingTool;
@@ -95,9 +95,9 @@ namespace JSC {
 
         bool isOpcode(Opcode);
         
 
         bool isOpcode(Opcode);
         
-        JSValue execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
+        JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
         JSValue execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
         JSValue execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
-        JSValue execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
+        JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
 
         JSValue retrieveArguments(CallFrame*, JSFunction*) const;
         JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
 
         JSValue retrieveArguments(CallFrame*, JSFunction*) const;
         JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
@@ -119,7 +119,7 @@ namespace JSC {
         void endRepeatCall(CallFrameClosure&);
         JSValue execute(CallFrameClosure&, JSValue* exception);
 
         void endRepeatCall(CallFrameClosure&);
         JSValue execute(CallFrameClosure&, JSValue* exception);
 
-        JSValue execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
+        JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
 
 #if USE(INTERPRETER)
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
 
 #if USE(INTERPRETER)
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
index 443455b..2b56a80 100644 (file)
@@ -2048,7 +2048,7 @@ PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* g
 {
     RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
     globalData->parser->arena().reset();
 {
     RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
     globalData->parser->arena().reset();
-    body->m_code.set(new CodeBlock(body.get()));
+    body->m_code.set(new NativeCodeBlock(body.get()));
     body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk()));
     return body.release();
 }
     body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk()));
     return body.release();
 }
@@ -2086,7 +2086,7 @@ void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
     ScopeChain scopeChain(scopeChainNode);
     JSGlobalObject* globalObject = scopeChain.globalObject();
 
     ScopeChain scopeChain(scopeChainNode);
     JSGlobalObject* globalObject = scopeChain.globalObject();
 
-    m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+    m_code.set(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
 
     OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
     generator->generate();
 
     OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
     generator->generate();
@@ -2112,7 +2112,7 @@ CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* sco
     ScopeChain scopeChain(scopeChainNode);
     JSGlobalObject* globalObject = scopeChain.globalObject();
 
     ScopeChain scopeChain(scopeChainNode);
     JSGlobalObject* globalObject = scopeChain.globalObject();
 
-    m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+    m_code.set(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
 
     OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
     generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
 
     OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
     generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
index 373dc00..4a991b2 100644 (file)
@@ -24,6 +24,7 @@
 #define Parser_h
 
 #include "Debugger.h"
 #define Parser_h
 
 #include "Debugger.h"
+#include "Executable.h"
 #include "Nodes.h"
 #include "SourceProvider.h"
 #include <wtf/Forward.h>
 #include "Nodes.h"
 #include "SourceProvider.h"
 #include <wtf/Forward.h>
@@ -41,9 +42,12 @@ namespace JSC {
 
     class Parser : public Noncopyable {
     public:
 
     class Parser : public Noncopyable {
     public:
-        template <class ParsedNode> PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
-        template <class ParsedNode> PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*);
+        template <class ParsedNode>
+        PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
+        template <class ParsedNode>
+        PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*);
         void reparseInPlace(JSGlobalData*, FunctionBodyNode*);
         void reparseInPlace(JSGlobalData*, FunctionBodyNode*);
+        PassRefPtr<FunctionBodyNode> parseFunctionFromGlobalCode(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
 
         void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
                               ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
 
         void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
                               ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
@@ -63,7 +67,8 @@ namespace JSC {
         int m_numConstants;
     };
 
         int m_numConstants;
     };
 
-    template <class ParsedNode> PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+    template <class ParsedNode>
+    PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
     {
         m_source = &source;
         parse(&exec->globalData(), errLine, errMsg);
     {
         m_source = &source;
         parse(&exec->globalData(), errLine, errMsg);
@@ -90,7 +95,8 @@ namespace JSC {
         return result.release();
     }
 
         return result.release();
     }
 
-    template <class ParsedNode> PassRefPtr<ParsedNode> Parser::reparse(JSGlobalData* globalData, ParsedNode* oldParsedNode)
+    template <class ParsedNode>
+    PassRefPtr<ParsedNode> Parser::reparse(JSGlobalData* globalData, ParsedNode* oldParsedNode)
     {
         m_source = &oldParsedNode->source();
         parse(globalData, 0, 0);
     {
         m_source = &oldParsedNode->source();
         parse(globalData, 0, 0);
@@ -115,6 +121,46 @@ namespace JSC {
         return result.release();
     }
 
         return result.release();
     }
 
+    inline PassRefPtr<FunctionBodyNode> Parser::parseFunctionFromGlobalCode(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+    {
+        RefPtr<ProgramNode> program = parse<ProgramNode>(exec, debugger, source, errLine, errMsg);
+
+        if (!program)
+            return 0;
+
+        StatementVector& children = program->children();
+        if (children.size() != 1)
+            return 0;
+
+        StatementNode* exprStatement = children[0];
+        ASSERT(exprStatement);
+        ASSERT(exprStatement->isExprStatement());
+        if (!exprStatement || !exprStatement->isExprStatement())
+            return 0;
+
+        ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+        ASSERT(funcExpr);
+        ASSERT(funcExpr->isFuncExprNode());
+        if (!funcExpr || !funcExpr->isFuncExprNode())
+            return 0;
+
+        RefPtr<FunctionBodyNode> body = static_cast<FuncExprNode*>(funcExpr)->body();
+        ASSERT(body);
+        return body.release();
+    }
+
+    template<class ASTNodeType, class CodeBlockType>
+    inline JSObject* TemplateExecutable<ASTNodeType, CodeBlockType>::parse(ExecState* exec, bool allowDebug)
+    {
+        int errLine;
+        UString errMsg;
+        m_node = exec->globalData().parser->parse<ASTNodeType>(exec, allowDebug ? exec->dynamicGlobalObject()->debugger() : 0, m_source, &errLine, &errMsg);
+
+        if (!m_node)
+            return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+        return 0;
+    }
+
 } // namespace JSC
 
 #endif // Parser_h
 } // namespace JSC
 
 #endif // Parser_h
index b8b1581..6ae5aa2 100644 (file)
@@ -41,30 +41,27 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
 {
     JSLock lock(exec);
 
 {
     JSLock lock(exec);
 
-    int errLine;
-    UString errMsg;
+    ProgramExecutable program(source);
+    JSObject* error = program.parse(exec);
+    if (error)
+        return Completion(Throw, error);
 
 
-    RefPtr<ProgramNode> progNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-    if (!progNode)
-        return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
     return Completion(Normal);
 }
 
 Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
 {
     JSLock lock(exec);
     return Completion(Normal);
 }
 
 Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
 {
     JSLock lock(exec);
-    
-    int errLine;
-    UString errMsg;
-    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
 
 
-    if (!programNode)
-        return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+    ProgramExecutable program(source);
+    JSObject* error = program.parse(exec);
+    if (error)
+        return Completion(Throw, error);
 
     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
 
     JSValue exception;
 
     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
 
     JSValue exception;
-    JSValue result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
+    JSValue result = exec->interpreter()->execute(&program, exec, scopeChain.node(), thisObj, &exception);
 
     if (exception) {
         if (exception.isObject() && asObject(exception)->isWatchdogException())
 
     if (exception) {
         if (exception.isObject() && asObject(exception)->isWatchdogException())
index db1d8cc..ddd4bc4 100644 (file)
@@ -97,6 +97,12 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
     return create(exec, type, message, -1, -1, NULL);
 }
 
     return create(exec, type, message, -1, -1, NULL);
 }
 
+JSObject* throwError(ExecState* exec, JSObject* error)
+{
+    exec->setException(error);
+    return error;
+}
+
 JSObject* throwError(ExecState* exec, ErrorType type)
 {
     JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
 JSObject* throwError(ExecState* exec, ErrorType type)
 {
     JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
index adf7fdf..e959cff 100644 (file)
@@ -59,6 +59,7 @@ namespace JSC {
     JSObject* throwError(ExecState*, ErrorType, const UString& message);
     JSObject* throwError(ExecState*, ErrorType, const char* message);
     JSObject* throwError(ExecState*, ErrorType);
     JSObject* throwError(ExecState*, ErrorType, const UString& message);
     JSObject* throwError(ExecState*, ErrorType, const char* message);
     JSObject* throwError(ExecState*, ErrorType);
+    JSObject* throwError(ExecState*, JSObject*);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
new file mode 100644 (file)
index 0000000..b781131
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 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 Executable_h
+#define Executable_h
+
+#include "Nodes.h"
+
+namespace JSC {
+
+    template<class ASTNodeType, class CodeBlockType>
+    class TemplateExecutable {
+    public:
+        TemplateExecutable(const SourceCode& source)
+            : m_source(source)
+        {
+        }
+
+        JSObject* parse(ExecState* exec, bool allowDebug = true);
+
+        void markAggregate(MarkStack& markStack)
+        {
+            m_node->markAggregate(markStack);
+        }
+
+        const UString& sourceURL() const { return m_node->sourceURL(); }
+        int lineNo() const { return m_node->lineNo(); }
+        CodeBlockType& bytecode(ScopeChainNode* scopeChainNode) { return m_node->bytecode(scopeChainNode); }
+        JITCode& jitCode(ScopeChainNode* scopeChainNode) { return m_node->jitCode(scopeChainNode); }
+
+    protected:
+        RefPtr<ASTNodeType> m_node;
+        SourceCode m_source;
+    };
+
+    class EvalExecutable : public TemplateExecutable<EvalNode, EvalCodeBlock>, public RefCounted<EvalExecutable> {
+    public:
+        EvalExecutable(const SourceCode& source)
+            : TemplateExecutable<EvalNode, EvalCodeBlock>(source)
+        {
+        }
+    };
+
+    class ProgramExecutable : public TemplateExecutable<ProgramNode, ProgramCodeBlock> {
+    public:
+        ProgramExecutable(const SourceCode& source)
+            : TemplateExecutable<ProgramNode, ProgramCodeBlock>(source)
+        {
+        }
+    };
+
+};
+
+#endif
index f4f5cc8..c5f7fa4 100644 (file)
@@ -66,32 +66,6 @@ CallType FunctionConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     return CallTypeHost;
 }
 
-FunctionBodyNode* extractFunctionBody(ProgramNode* program)
-{
-    if (!program)
-        return 0;
-
-    StatementVector& children = program->children();
-    if (children.size() != 1)
-        return 0;
-
-    StatementNode* exprStatement = children[0];
-    ASSERT(exprStatement);
-    ASSERT(exprStatement->isExprStatement());
-    if (!exprStatement || !exprStatement->isExprStatement())
-        return 0;
-
-    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
-    ASSERT(funcExpr);
-    ASSERT(funcExpr->isFuncExprNode());
-    if (!funcExpr || !funcExpr->isFuncExprNode())
-        return 0;
-
-    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
-    ASSERT(body);
-    return body;
-}
-
 // ECMA 15.3.2 The Function Constructor
 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
 {
 // ECMA 15.3.2 The Function Constructor
 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
 {
@@ -113,15 +87,13 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
     int errLine;
     UString errMsg;
     SourceCode source = makeSource(program, sourceURL, lineNumber);
     int errLine;
     UString errMsg;
     SourceCode source = makeSource(program, sourceURL, lineNumber);
-    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
-    FunctionBodyNode* body = extractFunctionBody(programNode.get());
+    RefPtr<FunctionBodyNode> body = exec->globalData().parser->parseFunctionFromGlobalCode(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
     if (!body)
         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
     if (!body)
         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
-    return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
+    return new (exec) JSFunction(exec, functionName, body.get(), scopeChain.node());
 }
 
 // ECMA 15.3.2 The Function Constructor
 }
 
 // ECMA 15.3.2 The Function Constructor
index 124b354..e8486dc 100644 (file)
@@ -26,8 +26,6 @@
 namespace JSC {
 
     class FunctionPrototype;
 namespace JSC {
 
     class FunctionPrototype;
-    class ProgramNode;
-    class FunctionBodyNode;
 
     class FunctionConstructor : public InternalFunction {
     public:
 
     class FunctionConstructor : public InternalFunction {
     public:
@@ -41,8 +39,6 @@ namespace JSC {
     JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
     JSObject* constructFunction(ExecState*, const ArgList&);
 
     JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
     JSObject* constructFunction(ExecState*, const ArgList&);
 
-    FunctionBodyNode* extractFunctionBody(ProgramNode*);
-
 } // namespace JSC
 
 #endif // FunctionConstructor_h
 } // namespace JSC
 
 #endif // FunctionConstructor_h
index 3746324..565bb85 100644 (file)
@@ -236,8 +236,7 @@ const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
 {
     if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
         initializingLazyNumericCompareFunction = true;
 {
     if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
         initializingLazyNumericCompareFunction = true;
-        RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
-        RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get());
+        RefPtr<FunctionBodyNode> functionBody = parser->parseFunctionFromGlobalCode(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
         lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions();
         initializingLazyNumericCompareFunction = false;
     }
         lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions();
         initializingLazyNumericCompareFunction = false;
     }
index 4268a54..2866e27 100644 (file)
@@ -112,8 +112,8 @@ JSGlobalObject::~JSGlobalObject()
     if (headObject == this)
         headObject = 0;
 
     if (headObject == this)
         headObject = 0;
 
-    HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
-    for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+    HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
+    for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
         (*it)->clearGlobalObject();
         
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
         (*it)->clearGlobalObject();
         
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
@@ -366,8 +366,8 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
 {
     JSVariableObject::markChildren(markStack);
     
 {
     JSVariableObject::markChildren(markStack);
     
-    HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
-    for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+    HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
+    for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
         (*it)->markAggregate(markStack);
 
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
         (*it)->markAggregate(markStack);
 
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
index 4dcaa76..ef7e9ce 100644 (file)
@@ -40,8 +40,8 @@ namespace JSC {
     class FunctionPrototype;
     class GlobalEvalFunction;
     class NativeErrorConstructor;
     class FunctionPrototype;
     class GlobalEvalFunction;
     class NativeErrorConstructor;
+    class GlobalCodeBlock;
     class ObjectConstructor;
     class ObjectConstructor;
-    class ProgramCodeBlock;
     class PrototypeFunction;
     class RegExpConstructor;
     class RegExpPrototype;
     class PrototypeFunction;
     class RegExpConstructor;
     class RegExpPrototype;
@@ -151,7 +151,7 @@ namespace JSC {
 
             RefPtr<JSGlobalData> globalData;
 
 
             RefPtr<JSGlobalData> globalData;
 
-            HashSet<ProgramCodeBlock*> codeBlocks;
+            HashSet<GlobalCodeBlock*> codeBlocks;
         };
 
     public:
         };
 
     public:
@@ -257,7 +257,7 @@ namespace JSC {
 
         virtual bool isDynamicScope() const;
 
 
         virtual bool isDynamicScope() const;
 
-        HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+        HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
 
         void copyGlobalsFrom(RegisterFile&);
         void copyGlobalsTo(RegisterFile&);
 
         void copyGlobalsFrom(RegisterFile&);
         void copyGlobalsTo(RegisterFile&);
index affb99c..50ea27f 100644 (file)
@@ -286,16 +286,12 @@ JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValu
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return parsedObject;
 
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return parsedObject;
 
-    int errLine;
-    UString errMsg;
+    EvalExecutable eval(makeSource(s));
+    JSObject* error = eval.parse(exec);
+    if (error)
+        return throwError(exec, error);
 
 
-    SourceCode source = makeSource(s);
-    RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
-    if (!evalNode)
-        return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL);
-
-    return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
+    return exec->interpreter()->execute(&eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
 }
 
 JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)