Reviewed by Eric Seidel.
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 Jan 2008 18:55:52 +0000 (18:55 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 Jan 2008 18:55:52 +0000 (18:55 +0000)
        - http://bugs.webkit.org/show_bug.cgi?id=16860
          a bit of cleanup after the Activation optimization

        * JavaScriptCore.exp: Export the GlobalExecState constructor instead of
        the global flavor of the ExecState constructor. It'd probably be cleaner
        to not export either one, but JSGlobalObject inlines the code that
        constructs the ExecState. If we changed that, we could remove this export.

        * JavaScriptCore.xcodeproj/project.pbxproj: Re-sorted a few things and
        put the new source files into the kjs group rather than at the top level.

        * kjs/ExecState.cpp:
        (KJS::ExecState::ExecState): Marked inline and updated for data member
        name changes. This is now only for use for the derived classes. Also removed
        code that sets the unused m_savedExec data member for the global case. That
        data member is only used for the other two types.
        (KJS::ExecState::~ExecState): Marked inline and removed all the code.
        The derived class destructors now inclde the appropriate code.
        (KJS::ExecState::lexicalGlobalObject): Removed unneeded special case for
        an empty scope chain. The bottom function already returns 0 for that case,
        so the general case code handles it fine. Also changed to use data members
        directly rather than calling functions.
        (KJS::GlobalExecState::GlobalExecState): Added. Calls through to the base
        class constructor.
        (KJS::GlobalExecState::~GlobalExecState): Added.
        (KJS::InterpreterExecState::InterpreterExecState): Added. Moved code to
        manipulate activeExecStates here since we don't want to have to check for the
        special case of globalExec.
        (KJS::InterpreterExecState::~InterpreterExecState): Added.
        (KJS::EvalExecState::EvalExecState): Added.
        (KJS::EvalExecState::~EvalExecState): Added.
        (KJS::FunctionExecState::FunctionExecState): Added.
        (KJS::FunctionExecState::~FunctionExecState): Added.

        * kjs/ExecState.h: Tweaked the header, includes, and declarations a bit.
        Made ExecState inherit from Noncopyable. Reformatted some comments and
        made them a bit more brief. Rearranged declarations a little bit and removed
        unused savedExec function. Changed seenLabels function to return a reference
        rather than a pointer. Made constructors and destructor protected, and also
        did the same with all data members. Renamed m_thisVal to m_thisValue and
        ls to m_labelStack. Added three new derived classes for each of the
        types of ExecState. The primary goal here was to remove a branch from the
        code in the destructor, but it's also clearer than overloading the arguments
        to the ExecState constructor.

        * kjs/JSGlobalObject.cpp:
        (KJS::getCurrentTime): Fixed formatting.
        (KJS::JSGlobalObject::pushActivation): Removed parentheses that don't make
        the expression clearer -- other similar sites didn't have these parentheses,
        even the one a couple lines earlier that sets stackEntry.
        (KJS::JSGlobalObject::tearOffActivation): Got rid of unneeded static_cast
        (I think I mentioned this during patch review) and used an early exit so that
        the entire contents of the function aren't nested inside an if statement.
        Also removed the check of codeType, instead checking Activation for 0.
        For now, I kept the codeType check, but inside an assertion.

        * kjs/JSGlobalObject.h: Changed type of globalExec to GlobalExecState.
        * kjs/function.cpp:
        (KJS::FunctionImp::callAsFunction): Changed type to FunctionExecState.
        (KJS::GlobalFuncImp::callAsFunction): Changed type to EvalExecState.
        * kjs/interpreter.cpp:
        (KJS::Interpreter::evaluate): Changed type to GlobalExecState.

        * kjs/nodes.cpp:
        (KJS::ContinueNode::execute): Changed code since seenLabels() returns a
        reference now instead of a pointer.
        (KJS::BreakNode::execute): Ditto.
        (KJS::LabelNode::execute): Ditto.

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

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/kjs/ExecState.cpp
JavaScriptCore/kjs/ExecState.h
JavaScriptCore/kjs/JSGlobalObject.cpp
JavaScriptCore/kjs/JSGlobalObject.h
JavaScriptCore/kjs/function.cpp
JavaScriptCore/kjs/interpreter.cpp
JavaScriptCore/kjs/nodes.cpp

index 3772da8..673a129 100644 (file)
@@ -1,3 +1,76 @@
+2008-01-26  Darin Adler  <darin@apple.com>
+
+        Reviewed by Eric Seidel.
+
+        - http://bugs.webkit.org/show_bug.cgi?id=16860
+          a bit of cleanup after the Activation optimization
+
+        * JavaScriptCore.exp: Export the GlobalExecState constructor instead of
+        the global flavor of the ExecState constructor. It'd probably be cleaner
+        to not export either one, but JSGlobalObject inlines the code that
+        constructs the ExecState. If we changed that, we could remove this export.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj: Re-sorted a few things and
+        put the new source files into the kjs group rather than at the top level.
+
+        * kjs/ExecState.cpp:
+        (KJS::ExecState::ExecState): Marked inline and updated for data member
+        name changes. This is now only for use for the derived classes. Also removed
+        code that sets the unused m_savedExec data member for the global case. That
+        data member is only used for the other two types.
+        (KJS::ExecState::~ExecState): Marked inline and removed all the code.
+        The derived class destructors now inclde the appropriate code.
+        (KJS::ExecState::lexicalGlobalObject): Removed unneeded special case for
+        an empty scope chain. The bottom function already returns 0 for that case,
+        so the general case code handles it fine. Also changed to use data members
+        directly rather than calling functions.
+        (KJS::GlobalExecState::GlobalExecState): Added. Calls through to the base
+        class constructor.
+        (KJS::GlobalExecState::~GlobalExecState): Added.
+        (KJS::InterpreterExecState::InterpreterExecState): Added. Moved code to
+        manipulate activeExecStates here since we don't want to have to check for the
+        special case of globalExec.
+        (KJS::InterpreterExecState::~InterpreterExecState): Added.
+        (KJS::EvalExecState::EvalExecState): Added.
+        (KJS::EvalExecState::~EvalExecState): Added.
+        (KJS::FunctionExecState::FunctionExecState): Added.
+        (KJS::FunctionExecState::~FunctionExecState): Added.
+
+        * kjs/ExecState.h: Tweaked the header, includes, and declarations a bit.
+        Made ExecState inherit from Noncopyable. Reformatted some comments and
+        made them a bit more brief. Rearranged declarations a little bit and removed
+        unused savedExec function. Changed seenLabels function to return a reference
+        rather than a pointer. Made constructors and destructor protected, and also
+        did the same with all data members. Renamed m_thisVal to m_thisValue and
+        ls to m_labelStack. Added three new derived classes for each of the
+        types of ExecState. The primary goal here was to remove a branch from the
+        code in the destructor, but it's also clearer than overloading the arguments
+        to the ExecState constructor.
+
+        * kjs/JSGlobalObject.cpp:
+        (KJS::getCurrentTime): Fixed formatting.
+        (KJS::JSGlobalObject::pushActivation): Removed parentheses that don't make
+        the expression clearer -- other similar sites didn't have these parentheses,
+        even the one a couple lines earlier that sets stackEntry.
+        (KJS::JSGlobalObject::tearOffActivation): Got rid of unneeded static_cast
+        (I think I mentioned this during patch review) and used an early exit so that
+        the entire contents of the function aren't nested inside an if statement.
+        Also removed the check of codeType, instead checking Activation for 0.
+        For now, I kept the codeType check, but inside an assertion.
+
+        * kjs/JSGlobalObject.h: Changed type of globalExec to GlobalExecState.
+        * kjs/function.cpp:
+        (KJS::FunctionImp::callAsFunction): Changed type to FunctionExecState.
+        (KJS::GlobalFuncImp::callAsFunction): Changed type to EvalExecState.
+        * kjs/interpreter.cpp:
+        (KJS::Interpreter::evaluate): Changed type to GlobalExecState.
+
+        * kjs/nodes.cpp:
+        (KJS::ContinueNode::execute): Changed code since seenLabels() returns a
+        reference now instead of a pointer.
+        (KJS::BreakNode::execute): Ditto.
+        (KJS::LabelNode::execute): Ditto.
+
 2008-01-26  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Mark Rowe.
index e7d5d5f..63ce4a2 100644 (file)
@@ -150,6 +150,7 @@ __ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
 __ZN3KJS14StringInstance4infoE
 __ZN3KJS14StringInstanceC1EPNS_8JSObjectERKNS_7UStringE
 __ZN3KJS14StringInstanceC2EPNS_8JSObjectERKNS_7UStringE
+__ZN3KJS15GlobalExecStateC1EPNS_14JSGlobalObjectE
 __ZN3KJS15JSWrapperObject4markEv
 __ZN3KJS15SavedPropertiesC1Ev
 __ZN3KJS15SavedPropertiesD1Ev
@@ -233,9 +234,6 @@ __ZN3KJS9Collector7collectEv
 __ZN3KJS9Collector7protectEPNS_7JSValueE
 __ZN3KJS9Collector9unprotectEPNS_7JSValueE
 __ZN3KJS9ExecState16activeExecStatesEv
-__ZN3KJS9ExecStateC1EPNS_14JSGlobalObjectE
-__ZN3KJS9ExecStateC1EPNS_14JSGlobalObjectEPNS_8JSObjectEPNS_11ProgramNodeE
-__ZN3KJS9ExecStateD1Ev
 __ZN3KJSeqERKNS_7UStringEPKc
 __ZN3WTF10fastCallocEmm
 __ZN3WTF10fastMallocEm
index b10105c..c53f236 100644 (file)
                7073BE3D0581291E005EE2C9 /* runtime_array.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = runtime_array.h; path = bindings/runtime_array.h; sourceTree = "<group>"; tabWidth = 8; };
                70B16A260569A10900DB756D /* runtime_object.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = runtime_object.cpp; path = bindings/runtime_object.cpp; sourceTree = "<group>"; tabWidth = 8; };
                70B16A270569A10900DB756D /* runtime_object.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = runtime_object.h; path = bindings/runtime_object.h; sourceTree = "<group>"; tabWidth = 8; };
-               7E2C6C950D31C6AB002D44E2 /* Activation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Activation.h; path = kjs/Activation.h; sourceTree = "<group>"; };
-               7E2C6C980D31C6B6002D44E2 /* scope_chain_mark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scope_chain_mark.h; path = kjs/scope_chain_mark.h; sourceTree = "<group>"; };
+               7E2C6C950D31C6AB002D44E2 /* Activation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Activation.h; sourceTree = "<group>"; };
+               7E2C6C980D31C6B6002D44E2 /* scope_chain_mark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scope_chain_mark.h; sourceTree = "<group>"; };
                84ABF1DE070B628C00A3AC05 /* npruntime_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = npruntime_impl.h; path = bindings/npruntime_impl.h; sourceTree = "<group>"; tabWidth = 8; };
                9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; };
                9303F5690991190000AD71B8 /* Noncopyable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Noncopyable.h; sourceTree = "<group>"; };
                0867D691FE84028FC02AAC07 /* JavaScriptCore */ = {
                        isa = PBXGroup;
                        children = (
-                               7E2C6C980D31C6B6002D44E2 /* scope_chain_mark.h */,
-                               7E2C6C950D31C6AB002D44E2 /* Activation.h */,
                                937B63CC09E766D200A671DD /* DerivedSources.make */,
                                14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */,
                                F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
-                               141211000A48772600480255 /* tests */,
-                               1432EBD70A34CAD400717B9F /* API */,
-                               65417200039E01BA0058BFEB /* kjs */,
                                65162EF108E6A21C007556CD /* wtf */,
-                               51856D950562EE9C008B9D83 /* bindings */,
                                65417203039E01F90058BFEB /* pcre */,
+                               65417200039E01BA0058BFEB /* kjs */,
+                               51856D950562EE9C008B9D83 /* bindings */,
+                               1432EBD70A34CAD400717B9F /* API */,
+                               141211000A48772600480255 /* tests */,
                                650FDF8D09D0FCA700769E54 /* Derived Sources */,
                                932FC3C20824BB70005B3C75 /* Resources */,
                                034768DFFF38A50411DB9C8B /* Products */,
                        isa = PBXGroup;
                        children = (
                                659126BC0BDD1728001921FB /* AllInOneFile.cpp */,
+                               7E2C6C950D31C6AB002D44E2 /* Activation.h */,
                                93ADFCE60CCBD7AC00D30B08 /* array_instance.cpp */,
                                938772E5038BFE19008635CE /* array_instance.h */,
                                F692A84D0255597D01FF60F7 /* array_object.cpp */,
                                65EA4C9A092AF9E20093D800 /* JSLock.h */,
                                14ABB454099C2A0F00E2A24F /* JSType.h */,
                                14F252600D08DF2F004ECFFF /* JSVariableObject.cpp */,
+                               14F252600D08DF2F004ECFFF /* JSVariableObject.cpp */,
                                14F252560D08DD8D004ECFFF /* JSVariableObject.h */,
                                65C7A1710A8EAACB00FA37EA /* JSWrapperObject.cpp */,
                                65C7A1720A8EAACB00FA37EA /* JSWrapperObject.h */,
                                14BD534A0A3E0AEA00BAF59C /* SavedBuiltins.h */,
                                9374D3A8038D9D74008635CE /* scope_chain.cpp */,
                                9374D3A7038D9D74008635CE /* scope_chain.h */,
+                               7E2C6C980D31C6B6002D44E2 /* scope_chain_mark.h */,
                                F692A87F0255597D01FF60F7 /* string_object.cpp */,
                                F692A8800255597D01FF60F7 /* string_object.h */,
                                14A396A60CD2933100B5B4FF /* SymbolTable.h */,
                                1482B6EB0A4300B300517CFC /* JSValueRef.h in Headers */,
                                14F252570D08DD8D004ECFFF /* JSVariableObject.h in Headers */,
                                65C7A1740A8EAACB00FA37EA /* JSWrapperObject.h in Headers */,
+                               1CAA8B4C0D32C39A0041BCFF /* JavaScript.h in Headers */,
+                               1CAA8B4D0D32C39A0041BCFF /* JavaScriptCore.h in Headers */,
                                932F5B610822A1C700736975 /* JavaScriptCorePrefix.h in Headers */,
                                65A7A5E00CD1D50E00061F8E /* LabelStack.h in Headers */,
                                657EB7460B708F540063461B /* ListHashSet.h in Headers */,
                                93E26BFE08B151D400F85226 /* ucpinternal.h in Headers */,
                                932F5B5C0822A1C700736975 /* ustring.h in Headers */,
                                14ABB36F099C076400E2A24F /* value.h in Headers */,
-                               1CAA8B4C0D32C39A0041BCFF /* JavaScript.h in Headers */,
-                               1CAA8B4D0D32C39A0041BCFF /* JavaScriptCore.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index d9471a7..b37523e 100644 (file)
@@ -1,9 +1,8 @@
 // -*- mode: c++; c-basic-offset: 4 -*-
 /*
- *  This file is part of the KDE libraries
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -42,7 +41,7 @@ static inline List* globalEmptyList()
 // ECMA 10.2
 
 // The constructor for the globalExec pseudo-ExecState
-ExecState::ExecState(JSGlobalObject* globalObject)
+inline ExecState::ExecState(JSGlobalObject* globalObject)
     : m_globalObject(globalObject)
     , m_exception(0)
     , m_propertyNames(CommonIdentifiers::shared())
@@ -54,7 +53,7 @@ ExecState::ExecState(JSGlobalObject* globalObject)
     , m_activation(0)
     , m_localStorage(&globalObject->localStorage())
     , m_variableObject(globalObject)
-    , m_thisVal(globalObject)
+    , m_thisValue(globalObject)
     , m_iterationDepth(0)
     , m_switchDepth(0) 
     , m_codeType(GlobalCode)
@@ -62,7 +61,7 @@ ExecState::ExecState(JSGlobalObject* globalObject)
     m_scopeChain.push(globalObject);
 }
 
-ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, ProgramNode* programNode)
+inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, ProgramNode* programNode)
     : m_globalObject(globalObject)
     , m_exception(0)
     , m_propertyNames(CommonIdentifiers::shared())
@@ -74,7 +73,7 @@ ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, Pro
     , m_activation(0)
     , m_localStorage(&globalObject->localStorage())
     , m_variableObject(globalObject)
-    , m_thisVal(globalObject)
+    , m_thisValue(globalObject)
     , m_iterationDepth(0)
     , m_switchDepth(0) 
     , m_codeType(GlobalCode)
@@ -83,11 +82,10 @@ ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, Pro
     // a script with a this object that's not the same as the global object is broken, and probably
     // has been for some time.
     ASSERT(m_scopeNode);
-    activeExecStates().append(this);
     m_scopeChain.push(globalObject);
 }
 
-ExecState::ExecState(JSGlobalObject* globalObject, EvalNode* evalNode, ExecState* callingExec)
+inline ExecState::ExecState(JSGlobalObject* globalObject, EvalNode* evalNode, ExecState* callingExec)
     : m_globalObject(globalObject)
     , m_exception(0)
     , m_propertyNames(callingExec->m_propertyNames)
@@ -100,18 +98,17 @@ ExecState::ExecState(JSGlobalObject* globalObject, EvalNode* evalNode, ExecState
     , m_localStorage(callingExec->m_localStorage)
     , m_scopeChain(callingExec->m_scopeChain)
     , m_variableObject(callingExec->m_variableObject)
-    , m_thisVal(callingExec->m_thisVal)
+    , m_thisValue(callingExec->m_thisValue)
     , m_iterationDepth(0)
     , m_switchDepth(0) 
     , m_codeType(EvalCode)
 {    
     ASSERT(m_scopeNode);
-    activeExecStates().append(this);
 }
 
-ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, 
-                     FunctionBodyNode* functionBodyNode, ExecState* callingExec,
-                     FunctionImp* func, const List& args)
+inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, 
+         FunctionBodyNode* functionBodyNode, ExecState* callingExec,
+         FunctionImp* func, const List& args)
     : m_globalObject(globalObject)
     , m_exception(0)
     , m_propertyNames(callingExec->m_propertyNames)
@@ -121,13 +118,12 @@ ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
     , m_function(func)
     , m_arguments(&args)
     , m_scopeChain(func->scope())
-    , m_thisVal(thisObject)
+    , m_thisValue(thisObject)
     , m_iterationDepth(0)
     , m_switchDepth(0) 
     , m_codeType(FunctionCode)
 {
     ASSERT(m_scopeNode);
-    activeExecStates().append(this);
 
     ActivationImp* activation = globalObject->pushActivation(this);
     m_activation = activation;
@@ -136,26 +132,16 @@ ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
     m_scopeChain.push(activation);
 }
 
-ExecState::~ExecState()
+inline ExecState::~ExecState()
 {
-    ASSERT(m_scopeNode && activeExecStates().last() == this || !m_scopeNode);
-    if (m_scopeNode)
-        activeExecStates().removeLast();
-
-    if (m_activation && m_activation->needsPop())
-        m_globalObject->popActivation();
 }
 
 JSGlobalObject* ExecState::lexicalGlobalObject() const
 {
-    if (scopeChain().isEmpty())
-        return dynamicGlobalObject();
-    
-    JSObject* object = scopeChain().bottom();
+    JSObject* object = m_scopeChain.bottom();
     if (object && object->isGlobalObject())
         return static_cast<JSGlobalObject*>(object);
-
-    return dynamicGlobalObject();
+    return m_globalObject;
 }
 
 void ExecState::markActiveExecStates() 
@@ -165,10 +151,65 @@ void ExecState::markActiveExecStates()
         (*it)->m_scopeChain.mark();
 }
 
-ExecStateStack& ExecState::activeExecStates()
+static inline ExecStateStack& inlineActiveExecStates()
 {
     static ExecStateStack staticActiveExecStates;
     return staticActiveExecStates;
 }
 
+ExecStateStack& ExecState::activeExecStates()
+{
+    return inlineActiveExecStates();
+}
+
+GlobalExecState::GlobalExecState(JSGlobalObject* globalObject)
+    : ExecState(globalObject)
+{
+}
+
+GlobalExecState::~GlobalExecState()
+{
+}
+
+InterpreterExecState::InterpreterExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
+    : ExecState(globalObject, thisObject, programNode)
+{
+    inlineActiveExecStates().append(this);
+}
+
+InterpreterExecState::~InterpreterExecState()
+{
+    ASSERT(inlineActiveExecStates().last() == this);
+    inlineActiveExecStates().removeLast();
+}
+
+EvalExecState::EvalExecState(JSGlobalObject* globalObject, EvalNode* evalNode, ExecState* callingExec)
+    : ExecState(globalObject, evalNode, callingExec)
+{
+    inlineActiveExecStates().append(this);
+}
+
+EvalExecState::~EvalExecState()
+{
+    ASSERT(inlineActiveExecStates().last() == this);
+    inlineActiveExecStates().removeLast();
+}
+
+FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject, 
+         FunctionBodyNode* functionBodyNode, ExecState* callingExec,
+         FunctionImp* func, const List& args)
+    : ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
+{
+    inlineActiveExecStates().append(this);
+}
+
+FunctionExecState::~FunctionExecState()
+{
+    ASSERT(inlineActiveExecStates().last() == this);
+    inlineActiveExecStates().removeLast();
+
+    if (m_activation->needsPop())
+        m_globalObject->popActivation();
+}
+
 } // namespace KJS
index 6efc74b..b63c4ca 100644 (file)
@@ -2,7 +2,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  */
 
-#ifndef ExecState_H
-#define ExecState_H
+#ifndef ExecState_h
+#define ExecState_h
 
 #include "LabelStack.h"
 #include "LocalStorage.h"
+#include "completion.h"
+#include "list.h"
 #include "scope_chain.h"
-#include "types.h"
 
 namespace KJS  {
 
-    enum CodeType {
-        GlobalCode,
-        EvalCode,
-        FunctionCode,
-    };
-    
     class ActivationImp;
     class CommonIdentifiers;
     class EvalNode;
@@ -47,29 +42,20 @@ namespace KJS  {
     class JSGlobalObject;
     class JSVariableObject;
     class ProgramNode;
-    class ScopeChain;
     class ScopeNode;
-    struct LocalStorageEntry;
+    
+    enum CodeType { GlobalCode, EvalCode, FunctionCode };
     
     typedef Vector<ExecState*, 16> ExecStateStack;
 
-    /**
-     * Represents the current state of script execution. This is
-     * passed as the first argument to most functions.
-     */
-    class ExecState {
-        friend class Interpreter;
-        friend class FunctionImp;
-        friend class GlobalFuncImp;
+    // Represents the current state of script execution.
+    // Passed as the first argument to most functions.
+    class ExecState : Noncopyable {
     public:
-        /**
-         * Returns the global object that was in scope when the current script started executing.
-         */
+        // Global object that was in scope when the current script started executing.
         JSGlobalObject* dynamicGlobalObject() const { return m_globalObject; }
         
-        /**
-         * Returns the global object that was in scope when the current body of code was defined.
-         */
+        // Global object that was in scope when the current body of code was defined.
         JSGlobalObject* lexicalGlobalObject() const;
                 
         void setException(JSValue* e) { m_exception = e; }
@@ -79,12 +65,14 @@ namespace KJS  {
         bool hadException() const { return !!m_exception; }
         
         const ScopeChain& scopeChain() const { return m_scopeChain; }
+        void pushScope(JSObject* s) { m_scopeChain.push(s); }
+        void popScope() { m_scopeChain.pop(); }
         void replaceScopeChainTop(JSObject* o) { m_scopeChain.replaceTop(o); }
         
         JSVariableObject* variableObject() const { return m_variableObject; }
         void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
         
-        JSObject* thisValue() const { return m_thisVal; }
+        JSObject* thisValue() const { return m_thisValue; }
         
         ExecState* callingExecState() { return m_callingExec; }
         
@@ -95,9 +83,7 @@ namespace KJS  {
         FunctionImp* function() const { return m_function; }
         const List* arguments() const { return m_arguments; }
         
-        void pushScope(JSObject* s) { m_scopeChain.push(s); }
-        void popScope() { m_scopeChain.pop(); }
-        LabelStack* seenLabels() { return &ls; }
+        LabelStack& seenLabels() { return m_labelStack; }
         
         void pushIteration() { m_iterationDepth++; }
         void popIteration() { m_iterationDepth--; }
@@ -177,6 +163,10 @@ namespace KJS  {
             return 0;
         }
 
+        static void markActiveExecStates();
+        static ExecStateStack& activeExecStates();
+
+    protected:
         ExecState(JSGlobalObject*);
         ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
         ExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState);
@@ -184,10 +174,6 @@ namespace KJS  {
             ExecState* callingExecState, FunctionImp*, const List& args);
         ~ExecState();
 
-        static void markActiveExecStates();
-        static ExecStateStack& activeExecStates();
-
-    private:
         // ExecStates are always stack-allocated, and the garbage collector
         // marks the stack, so we don't need to protect the objects below from GC.
 
@@ -207,9 +193,9 @@ namespace KJS  {
 
         ScopeChain m_scopeChain;
         JSVariableObject* m_variableObject;
-        JSObject* m_thisVal;
+        JSObject* m_thisValue;
         
-        LabelStack ls;
+        LabelStack m_labelStack;
         int m_iterationDepth;
         int m_switchDepth;
         CodeType m_codeType;
@@ -218,6 +204,31 @@ namespace KJS  {
         const Identifier* m_breakOrContinueTarget;
     };
 
+    class GlobalExecState : public ExecState {
+    public:
+        GlobalExecState(JSGlobalObject*);
+        ~GlobalExecState();
+    };
+
+    class InterpreterExecState : public ExecState {
+    public:
+        InterpreterExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
+        ~InterpreterExecState();
+    };
+
+    class EvalExecState : public ExecState {
+    public:
+        EvalExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState);
+        ~EvalExecState();
+    };
+
+    class FunctionExecState : public ExecState {
+    public:
+        FunctionExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*,
+            ExecState* callingExecState, FunctionImp*, const List& args);
+        ~FunctionExecState();
+    };
+
 } // namespace KJS
 
-#endif // ExecState_H
+#endif // ExecState_h
index ff02853..67d39ae 100644 (file)
@@ -73,7 +73,8 @@ static inline void markIfNeeded(JSValue* v)
 // Returns the current time in milliseconds
 // It doesn't matter what "current time" is here, just as long as
 // it's possible to measure the time difference correctly.
-static inline unsigned getCurrentTime() {
+static inline unsigned getCurrentTime()
+{
 #if HAVE(SYS_TIME_H)
     struct timeval tv;
     gettimeofday(&tv, 0);
@@ -522,8 +523,7 @@ ActivationImp* JSGlobalObject::pushActivation(ExecState* exec)
     
     StackActivation* stackEntry = &d()->activations->data[d()->activationCount++];
     stackEntry->activationStorage.init(exec);
-    
-    return &(stackEntry->activationStorage);
+    return &stackEntry->activationStorage;
 }
 
 inline void JSGlobalObject::checkActivationCount()
@@ -544,22 +544,24 @@ void JSGlobalObject::popActivation()
 
 void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic)
 {
-    if (exec->codeType() == FunctionCode && static_cast<ActivationImp*>(exec->activationObject())->isOnStack()) {
-        ActivationImp* oldActivation = static_cast<ActivationImp*>(exec->activationObject());
-        ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic);
-        
-        if (!leaveRelic) {
-            checkActivationCount();
-            d()->activationCount--;
-        }
-        
-        oldActivation->d()->localStorage.shrink(0);
-        
-        exec->setActivationObject(newActivation);
-        exec->setVariableObject(newActivation);
-        exec->setLocalStorage(&(newActivation->localStorage()));
-        exec->replaceScopeChainTop(newActivation);
+    ActivationImp* oldActivation = exec->activationObject();
+    if (!oldActivation || !oldActivation->isOnStack())
+        return;
+
+    ASSERT(exec->codeType() == FunctionCode);
+    ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic);
+    
+    if (!leaveRelic) {
+        checkActivationCount();
+        d()->activationCount--;
     }
+    
+    oldActivation->d()->localStorage.shrink(0);
+    
+    exec->setActivationObject(newActivation);
+    exec->setVariableObject(newActivation);
+    exec->setLocalStorage(&newActivation->localStorage());
+    exec->replaceScopeChainTop(newActivation);
 }
 
 } // namespace KJS
index ec79ae2..2568b0a 100644 (file)
@@ -86,7 +86,7 @@ namespace KJS {
             Debugger* debugger;
             CompatMode compatMode;
             
-            ExecState globalExec;
+            GlobalExecState globalExec;
             int recursion;
 
             unsigned timeoutTime;
index 92b2f2f..23851a1 100644 (file)
@@ -72,7 +72,7 @@ void FunctionImp::mark()
 
 JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
-    ExecState newExec(exec->dynamicGlobalObject(), thisObj, body.get(), exec, this, args);
+    FunctionExecState newExec(exec->dynamicGlobalObject(), thisObj, body.get(), exec, this, args);
     JSValue* result = body->execute(&newExec);
     if (newExec.completionType() == Throw) {
         exec->setException(result);
@@ -721,7 +721,7 @@ JSValue* globalFuncEval(ExecState* exec, JSObject* thisObj, const List& args)
     // enter a new execution context
     exec->dynamicGlobalObject()->tearOffActivation(exec);
     JSGlobalObject* globalObject = switchGlobal ? static_cast<JSGlobalObject*>(thisObj) : exec->dynamicGlobalObject();
-    ExecState newExec(globalObject, evalNode.get(), exec);
+    EvalExecState newExec(globalObject, evalNode.get(), exec);
 
     if (switchGlobal) {
         newExec.pushScope(thisObj);
index 4e92252..0d515ac 100644 (file)
@@ -119,7 +119,7 @@ Completion Interpreter::evaluate(ExecState* exec, const UString& sourceURL, int
         res = Completion(Throw, exec->exception());
     else {
         // execute the code
-        ExecState newExec(globalObject, thisObj, progNode.get());
+        InterpreterExecState newExec(globalObject, thisObj, progNode.get());
         JSValue* value = progNode->execute(&newExec);
         res = Completion(newExec.completionType(), value);
     }
index 2099643..9810336 100644 (file)
@@ -1013,11 +1013,11 @@ JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
       args->evaluateList(exec, argList);
       KJS_CHECKEXCEPTIONVALUE
         
-      JSObject *thisObj = base;
+      JSObjectthisObj = base;
       // ECMA 11.2.3 says that in this situation the this value should be null.
       // However, section 10.2.3 says that in the case where the value provided
       // by the caller is null, the global object should be used. It also says
-      // that the section does not apply to interal functions, but for simplicity
+      // that the section does not apply to internal functions, but for simplicity
       // of implementation we use the global object anyway here. This guarantees
       // that in host objects you always get a valid object for this.
       if (thisObj->isActivationObject())
@@ -3953,7 +3953,7 @@ JSValue* ContinueNode::execute(ExecState* exec)
 {
   if (ident.isEmpty() && !exec->inIteration())
     return setErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
-  if (!ident.isEmpty() && !exec->seenLabels()->contains(ident))
+  if (!ident.isEmpty() && !exec->seenLabels().contains(ident))
     return setErrorCompletion(exec, SyntaxError, "Label %s not found.", ident);
   return exec->setContinueCompletion(&ident);
 }
@@ -3965,7 +3965,7 @@ JSValue* BreakNode::execute(ExecState *exec)
 {
   if (ident.isEmpty() && !exec->inIteration() && !exec->inSwitch())
     return setErrorCompletion(exec, SyntaxError, "Invalid break statement.");
-  if (!ident.isEmpty() && !exec->seenLabels()->contains(ident))
+  if (!ident.isEmpty() && !exec->seenLabels().contains(ident))
     return setErrorCompletion(exec, SyntaxError, "Label %s not found.");
   return exec->setBreakCompletion(&ident);
 }
@@ -4160,10 +4160,10 @@ void LabelNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStac
 // ECMA 12.12
 JSValue* LabelNode::execute(ExecState *exec)
 {
-  if (!exec->seenLabels()->push(label))
+  if (!exec->seenLabels().push(label))
     return setErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
   JSValue* result = statement->execute(exec);
-  exec->seenLabels()->pop();
+  exec->seenLabels().pop();
 
   if (exec->completionType() == Break && exec->breakOrContinueTarget() == label)
     exec->setCompletionType(Normal);