Commit 8356d838 authored by mjs@apple.com's avatar mjs@apple.com

2008-03-20 Maciej Stachowiak <mjs@apple.com>

        Reviewed by Oliver.
        
        - reduce function call overhead for 1.014x speedup on SunSpider

        I moved some functions from ExecState.cpp to ExecStateInline.h and
        from JSGlobalObject.cpp to JSGlobalObject.h, and declared them
        inline; machine function call overhead for these was hurting JS
        funcion call overhead.
        
        * kjs/ExecState.cpp:
        * kjs/ExecStateInlines.h: Added.
        (KJS::ExecState::ExecState):
        (KJS::ExecState::~ExecState):
        (KJS::FunctionExecState::FunctionExecState):
        (KJS::FunctionExecState::~FunctionExecState):
        * kjs/JSGlobalObject.cpp:
        * kjs/JSGlobalObject.h:
        (KJS::JSGlobalObject::pushActivation):
        (KJS::JSGlobalObject::checkActivationCount):
        (KJS::JSGlobalObject::popActivation):
        * kjs/function.cpp:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31173 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c635d17d
2008-03-20 Maciej Stachowiak <mjs@apple.com>
Reviewed by Oliver.
- reduce function call overhead for 1.014x speedup on SunSpider
I moved some functions from ExecState.cpp to ExecStateInline.h and
from JSGlobalObject.cpp to JSGlobalObject.h, and declared them
inline; machine function call overhead for these was hurting JS
funcion call overhead.
* kjs/ExecState.cpp:
* kjs/ExecStateInlines.h: Added.
(KJS::ExecState::ExecState):
(KJS::ExecState::~ExecState):
(KJS::FunctionExecState::FunctionExecState):
(KJS::FunctionExecState::~FunctionExecState):
* kjs/JSGlobalObject.cpp:
* kjs/JSGlobalObject.h:
(KJS::JSGlobalObject::pushActivation):
(KJS::JSGlobalObject::checkActivationCount):
(KJS::JSGlobalObject::popActivation):
* kjs/function.cpp:
2008-03-19 Oliver Hunt <oliver@apple.com>
Reviewed by Maciej.
......
......@@ -29,6 +29,7 @@
#include "function.h"
#include "internal.h"
#include "scope_chain_mark.h"
#include "ExecStateInlines.h"
namespace KJS {
......@@ -109,44 +110,6 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
ASSERT(m_scopeNode);
}
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)
, m_emptyList(callingExec->m_emptyList)
, m_callingExec(callingExec)
, m_scopeNode(functionBodyNode)
, m_function(func)
, m_arguments(&args)
, m_scopeChain(func->scope())
, m_inlineScopeChainNode(0, 0)
, m_thisValue(thisObject)
, m_iterationDepth(0)
, m_switchDepth(0)
, m_codeType(FunctionCode)
{
ASSERT(m_scopeNode);
ActivationImp* activation = globalObject->pushActivation(this);
m_activation = activation;
m_localStorage = &activation->localStorage();
m_variableObject = activation;
if (functionBodyNode->usesEval() || functionBodyNode->needsClosure())
m_scopeChain.push(activation);
else {
m_inlineScopeChainNode.object = activation;
// The ScopeChain will ref this node itself, so we don't need to worry about
// anything trying to delete our scopenode
m_scopeChain.push(&m_inlineScopeChainNode);
}
}
inline ExecState::~ExecState()
{
}
JSGlobalObject* ExecState::lexicalGlobalObject() const
{
JSObject* object = m_scopeChain.bottom();
......@@ -187,22 +150,5 @@ EvalExecState::~EvalExecState()
ASSERT(m_globalObject->activeExecStates().last() == this);
m_globalObject->activeExecStates().removeLast();
}
FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject,
FunctionBodyNode* functionBodyNode, ExecState* callingExec,
FunctionImp* func, const List& args)
: ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
{
m_globalObject->activeExecStates().append(this);
}
FunctionExecState::~FunctionExecState()
{
ASSERT(m_globalObject->activeExecStates().last() == this);
m_globalObject->activeExecStates().removeLast();
if (m_activation->needsPop())
m_globalObject->popActivation();
}
} // namespace KJS
// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* 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
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef ExecStateInlines_h
#define ExecStateInlines_h
#include "ExecState.h"
#include "function.h"
#include "JSGlobalObject.h"
namespace KJS {
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)
, m_emptyList(callingExec->m_emptyList)
, m_callingExec(callingExec)
, m_scopeNode(functionBodyNode)
, m_function(func)
, m_arguments(&args)
, m_scopeChain(func->scope())
, m_inlineScopeChainNode(0, 0)
, m_thisValue(thisObject)
, m_iterationDepth(0)
, m_switchDepth(0)
, m_codeType(FunctionCode)
{
ASSERT(m_scopeNode);
ActivationImp* activation = globalObject->pushActivation(this);
m_activation = activation;
m_localStorage = &activation->localStorage();
m_variableObject = activation;
if (functionBodyNode->usesEval() || functionBodyNode->needsClosure())
m_scopeChain.push(activation);
else {
m_inlineScopeChainNode.object = activation;
// The ScopeChain will ref this node itself, so we don't need to worry about
// anything trying to delete our scopenode
m_scopeChain.push(&m_inlineScopeChainNode);
}
}
inline ExecState::~ExecState()
{
}
inline FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject,
FunctionBodyNode* functionBodyNode, ExecState* callingExec,
FunctionImp* func, const List& args)
: ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
{
m_globalObject->activeExecStates().append(this);
}
inline FunctionExecState::~FunctionExecState()
{
ASSERT(m_globalObject->activeExecStates().last() == this);
m_globalObject->activeExecStates().removeLast();
if (m_activation->needsPop())
m_globalObject->popActivation();
}
} // namespace KJS
#endif // ExecStateInlines_h
......@@ -530,37 +530,6 @@ ExecState* JSGlobalObject::globalExec()
return &d()->globalExec;
}
ActivationImp* JSGlobalObject::pushActivation(ExecState* exec)
{
if (d()->activationCount == activationStackNodeSize) {
ActivationStackNode* newNode = new ActivationStackNode;
newNode->prev = d()->activations;
d()->activations = newNode;
d()->activationCount = 0;
}
StackActivation* stackEntry = &d()->activations->data[d()->activationCount++];
stackEntry->activationStorage.init(exec);
return &stackEntry->activationStorage;
}
inline void JSGlobalObject::checkActivationCount()
{
if (!d()->activationCount) {
ActivationStackNode* prev = d()->activations->prev;
ASSERT(prev);
delete d()->activations;
d()->activations = prev;
d()->activationCount = activationStackNodeSize;
}
}
void JSGlobalObject::popActivation()
{
checkActivationCount();
d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0);
}
void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic)
{
ActivationImp* oldActivation = exec->activationObject();
......
......@@ -24,6 +24,7 @@
#define KJS_GlobalObject_h
#include "JSVariableObject.h"
#include "Activation.h"
namespace KJS {
......@@ -263,6 +264,37 @@ namespace KJS {
return checkTimeout();
}
inline ActivationImp* JSGlobalObject::pushActivation(ExecState* exec)
{
if (d()->activationCount == activationStackNodeSize) {
ActivationStackNode* newNode = new ActivationStackNode;
newNode->prev = d()->activations;
d()->activations = newNode;
d()->activationCount = 0;
}
StackActivation* stackEntry = &d()->activations->data[d()->activationCount++];
stackEntry->activationStorage.init(exec);
return &stackEntry->activationStorage;
}
inline void JSGlobalObject::checkActivationCount()
{
if (!d()->activationCount) {
ActivationStackNode* prev = d()->activations->prev;
ASSERT(prev);
delete d()->activations;
d()->activations = prev;
d()->activationCount = activationStackNodeSize;
}
}
inline void JSGlobalObject::popActivation()
{
checkActivationCount();
d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0);
}
} // namespace KJS
#endif // KJS_GlobalObject_h
......@@ -39,6 +39,7 @@
#include "nodes.h"
#include "operations.h"
#include "scope_chain_mark.h"
#include "ExecStateInlines.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment