Reviewed by Oliver.
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Jan 2008 08:43:59 +0000 (08:43 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Jan 2008 08:43:59 +0000 (08:43 +0000)
        - http://bugs.webkit.org/show_bug.cgi?id=16684
          eliminate debugger overhead from function body execution

        Speeds SunSpider up 1.003x. That's a small amount, but measurable.

        * JavaScriptCore.exp: Updated.
        * kjs/Parser.h:
        (KJS::Parser::parse): Create the node with a static member function named create() instead
        of using new explicitly.

        * kjs/grammar.y: Changed calls to new FunctionBodyNode to use FunctionBodyNode::create().

        * kjs/nodes.cpp:
        (KJS::ProgramNode::create): Added. Calls new.
        (KJS::EvalNode::create): Ditto.
        (KJS::FunctionBodyNode::create): Ditto, but creates FunctionBodyNodeWithDebuggerHooks
        when a debugger is present.
        (KJS::FunctionBodyNode::execute): Removed debugger hooks.
        (KJS::FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks): Added.
        (KJS::FunctionBodyNodeWithDebuggerHooks::execute): Calls the debugger, then the code,
        then the debugger again.

        * kjs/nodes.h: Added create functions, made the constructors private and protected.

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

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/kjs/Parser.h
JavaScriptCore/kjs/grammar.y
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h

index baf8b46..19d554b 100644 (file)
@@ -1,3 +1,31 @@
+2008-01-01  Darin Adler  <darin@apple.com>
+
+        Reviewed by Oliver.
+
+        - http://bugs.webkit.org/show_bug.cgi?id=16684
+          eliminate debugger overhead from function body execution
+
+        Speeds SunSpider up 1.003x. That's a small amount, but measurable.
+
+        * JavaScriptCore.exp: Updated.
+        * kjs/Parser.h:
+        (KJS::Parser::parse): Create the node with a static member function named create() instead
+        of using new explicitly.
+
+        * kjs/grammar.y: Changed calls to new FunctionBodyNode to use FunctionBodyNode::create().
+
+        * kjs/nodes.cpp:
+        (KJS::ProgramNode::create): Added. Calls new.
+        (KJS::EvalNode::create): Ditto.
+        (KJS::FunctionBodyNode::create): Ditto, but creates FunctionBodyNodeWithDebuggerHooks
+        when a debugger is present.
+        (KJS::FunctionBodyNode::execute): Removed debugger hooks.
+        (KJS::FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks): Added.
+        (KJS::FunctionBodyNodeWithDebuggerHooks::execute): Calls the debugger, then the code,
+        then the debugger again.
+
+        * kjs/nodes.h: Added create functions, made the constructors private and protected.
+
 2007-12-30  Eric Seidel  <eric@webkit.org>
 
         Reviewed by Sam.
index 03f15af..beed87e 100644 (file)
@@ -120,7 +120,7 @@ __ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERKNS_7UStringEiS5_PNS_7JSValueE
 __ZN3KJS11JSImmediate4typeEPKNS_7JSValueE
 __ZN3KJS11JSImmediate8toObjectEPKNS_7JSValueEPNS_9ExecStateE
 __ZN3KJS11JSImmediate8toStringEPKNS_7JSValueE
-__ZN3KJS11ProgramNodeC1EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE
+__ZN3KJS11ProgramNode6createEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE
 __ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierE
 __ZN3KJS11PropertyMap5clearEv
 __ZN3KJS11PropertyMap7restoreERKNS_15SavedPropertiesE
index f2ab3c5..92548fe 100644 (file)
@@ -84,9 +84,9 @@ namespace KJS {
             m_sourceURL = UString();
             return 0;
         }
-        RefPtr<ParsedNode> node = new ParsedNode(m_sourceElements.release().get(),
-                                                 m_varDeclarations ? &m_varDeclarations->data : 0, 
-                                                 m_funcDeclarations ? &m_funcDeclarations->data : 0);
+        RefPtr<ParsedNode> node = ParsedNode::create(m_sourceElements.release().get(),
+                                                     m_varDeclarations ? &m_varDeclarations->data : 0, 
+                                                     m_funcDeclarations ? &m_funcDeclarations->data : 0);
         m_varDeclarations = 0;
         m_funcDeclarations = 0;
         m_sourceURL = UString();
index 427ac8e..82d148d 100644 (file)
@@ -1001,9 +1001,9 @@ FormalParameterList:
 ;
 
 FunctionBody:
-    /* not in spec */           { $$ = new FunctionBodyNode(0, 0, 0); }
-  | SourceElements              { $$ = new FunctionBodyNode($1.m_node, $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0, 
-                                                            $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0);
+    /* not in spec */           { $$ = FunctionBodyNode::create(0, 0, 0); }
+  | SourceElements              { $$ = FunctionBodyNode::create($1.m_node, $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0, 
+                                                                $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0);
                                   // As in mergeDeclarationLists() we have to ref/deref to safely get rid of
                                   // the declaration lists.
                                   if ($1.m_varDeclarations) {
index 4138e39..af47dcd 100644 (file)
 
 namespace KJS {
 
+    class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
+    public:
+        FunctionBodyNodeWithDebuggerHooks(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
+        virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+    };
+
 #define KJS_CHECKEXCEPTION \
   if (exec->hadException()) \
     return rethrowException(exec);
@@ -4225,17 +4231,34 @@ ProgramNode::ProgramNode(SourceElements* children, DeclarationStacks::VarStack*
 {
 }
 
+ProgramNode* ProgramNode::create(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
+{
+    return new ProgramNode(children, varStack, funcStack);
+}
+
 EvalNode::EvalNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     : ScopeNode(children, varStack, funcStack)
 {
 }
 
+EvalNode* EvalNode::create(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
+{
+    return new EvalNode(children, varStack, funcStack);
+}
+
 FunctionBodyNode::FunctionBodyNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     : ScopeNode(children, varStack, funcStack)
     , m_initialized(false)
 {
 }
 
+FunctionBodyNode* FunctionBodyNode::create(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
+{
+    if (Debugger::debuggersPresent)
+        return new FunctionBodyNodeWithDebuggerHooks(children, varStack, funcStack);
+    return new FunctionBodyNode(children, varStack, funcStack);
+}
+
 void FunctionBodyNode::initializeSymbolTable(ExecState* exec)
 {
     SymbolTable& symbolTable = exec->variableObject()->symbolTable();
@@ -4474,16 +4497,28 @@ JSValue* EvalNode::execute(ExecState* exec)
 JSValue* FunctionBodyNode::execute(ExecState* exec)
 {
     processDeclarations(exec);
+    return ScopeNode::execute(exec);
+}
+
+// ------------------------------ FunctionBodyNodeWithDebuggerHooks ---------------------------------
+
+FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks(SourceElements* children,
+        DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
+    : FunctionBodyNode(children, varStack, funcStack)
+{
+}
 
+JSValue* FunctionBodyNodeWithDebuggerHooks::execute(ExecState* exec)
+{
     if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
         if (!dbg->callEvent(exec, sourceId(), lineNo(), exec->function(), *exec->arguments())) {
             dbg->imp()->abort();
             return exec->setInterruptedCompletion();
         }
-    }    
-    
-    JSValue* result = ScopeNode::execute(exec);
-    
+    }
+
+    JSValue* result = FunctionBodyNode::execute(exec);
+
     if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
         if (exec->completionType() == Throw)
             exec->setException(result);
@@ -4493,7 +4528,6 @@ JSValue* FunctionBodyNode::execute(ExecState* exec)
         }
     }
 
-    
     return result;
 }
 
index 4fbd91d..2fdabd2 100644 (file)
@@ -1968,10 +1968,11 @@ namespace KJS {
 
   class ProgramNode : public ScopeNode {
   public:
-    ProgramNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
+    static ProgramNode* create(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
     virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
     
   private:
+    ProgramNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
     void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
     ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
 
@@ -1981,16 +1982,17 @@ namespace KJS {
 
   class EvalNode : public ScopeNode {
   public:
-    EvalNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
+    static EvalNode* create(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
     virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
     
   private:
+    EvalNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
     ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
   };
 
   class FunctionBodyNode : public ScopeNode {
   public:
-    FunctionBodyNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
+    static FunctionBodyNode* create(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
 
     virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
 
@@ -1999,6 +2001,9 @@ namespace KJS {
     Vector<Identifier>& parameters() KJS_FAST_CALL { return m_parameters; }
     UString paramString() const KJS_FAST_CALL;
 
+  protected:
+    FunctionBodyNode(SourceElements*, DeclarationStacks::VarStack*, DeclarationStacks::FunctionStack*) KJS_FAST_CALL;
+
   private:
     void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
     ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;