Commit c635d17d authored by oliver@apple.com's avatar oliver@apple.com

Avoid heap allocating the root scope chain node for eval and closure free functions

Reviewed by Maciej

Maciej suggested using an inline ScopeChainNode for functions that don't use eval
or closures as they are unable to ever capture the scope chain.  This gives us a 2.4%
win in sunspider, a 15% win in controlflow-recursive, and big (>5%) wins in a number
of other tests.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31172 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2e1b301a
2008-03-19 Oliver Hunt <oliver@apple.com>
Reviewed by Maciej.
Avoid heap allocating the root scope chain node for eval and closure free functions
Maciej suggested using an inline ScopeChainNode for functions that don't use eval
or closures as they are unable to ever capture the scope chain. This gives us a 2.4%
win in sunspider, a 15% win in controlflow-recursive, and big (>5%) wins in a number
of other tests.
* kjs/ExecState.cpp:
(KJS::ExecState::ExecState):
* kjs/ExecState.h:
* kjs/scope_chain.h:
(KJS::ScopeChain::push):
2008-03-19 Mark Rowe <mrowe@apple.com>
Reviewed by Sam Weinig.
......
......@@ -52,6 +52,7 @@ inline ExecState::ExecState(JSGlobalObject* globalObject)
, m_arguments(0)
, m_activation(0)
, m_localStorage(&globalObject->localStorage())
, m_inlineScopeChainNode(0, 0)
, m_variableObject(globalObject)
, m_thisValue(globalObject)
, m_iterationDepth(0)
......@@ -72,6 +73,7 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject
, m_arguments(0)
, m_activation(0)
, m_localStorage(&globalObject->localStorage())
, m_inlineScopeChainNode(0, 0)
, m_variableObject(globalObject)
, m_thisValue(globalObject)
, m_iterationDepth(0)
......@@ -97,6 +99,7 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
, m_activation(0)
, m_localStorage(callingExec->m_localStorage)
, m_scopeChain(scopeChain)
, m_inlineScopeChainNode(0, 0)
, m_variableObject(variableObject)
, m_thisValue(thisObject)
, m_iterationDepth(0)
......@@ -118,6 +121,7 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
, m_function(func)
, m_arguments(&args)
, m_scopeChain(func->scope())
, m_inlineScopeChainNode(0, 0)
, m_thisValue(thisObject)
, m_iterationDepth(0)
, m_switchDepth(0)
......@@ -129,7 +133,14 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
m_activation = activation;
m_localStorage = &activation->localStorage();
m_variableObject = activation;
m_scopeChain.push(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()
......
......@@ -188,6 +188,7 @@ namespace KJS {
LocalStorage* m_localStorage;
ScopeChain m_scopeChain;
ScopeChainNode m_inlineScopeChainNode;
JSVariableObject* m_variableObject;
JSObject* m_thisValue;
......
......@@ -90,6 +90,7 @@ namespace KJS {
void clear() { deref(); _node = 0; }
void push(JSObject *);
void push(const ScopeChain &);
void push(ScopeChainNode*);
void replaceTop(JSObject*);
void pop();
......@@ -140,6 +141,15 @@ inline void ScopeChain::push(JSObject *o)
_node = new ScopeChainNode(_node, o);
}
inline void ScopeChain::push(ScopeChainNode *node)
{
ASSERT(node);
ASSERT(node->object);
node->refCount++;
node->next = _node;
_node = node;
}
inline void ScopeChain::replaceTop(JSObject* o)
{
ASSERT(o);
......
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