Commit 8d450d34 authored by darin's avatar darin

JavaScriptCore:

	- changed ScopeChain to not ref each item in the chain, and use
        marking instead; gains 1% on JavaScript iBench

        * kjs/context.h: Return chain by reference.
        * kjs/internal.cpp: (ContextImp::mark): Mark the scope chain.
        * kjs/interpreter.cpp: (Context::scopeChain): Return chain by reference.
        * kjs/interpreter.h: Make some Context methods inline.
        * kjs/nodes.cpp:
        (ThisNode::evaluate): Get at ContextImp directly.
        (ResolveNode::evaluateReference): Ditto.
        (VarDeclNode::evaluate): Ditto.
        (VarDeclNode::processVarDecls): Ditto.
        (FuncDeclNode::processFuncDecl): Pass ScopeChain directly to avoid copying.
        (FuncExprNode::evaluate): Ditto.
        * kjs/object.cpp: Make scope and setScope inline.
        * kjs/object.h: Make scope return a chain by reference. Make scope and
	setScope both be inline. Use a normal ScopeChain instead of NoRefScopeChain
	since they are now one and the same.
        * kjs/scope_chain.cpp: Remove all the code to ref and deref objects.
	Merge NoRefScopeChain in with ScopeChain since they both work this way now.
        * kjs/scope_chain.h: Remove NoRefScopeChain and simplify the ref counts.
	Make more functions inline.

WebCore:

        * force-js-clean-timestamp: Touch for ScopeChain change.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2851 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 828fb841
2002-11-24 Darin Adler <darin@apple.com>
- changed ScopeChain to not ref each item in the chain, and use
marking instead; gains 1% on JavaScript iBench
* kjs/context.h: Return chain by reference.
* kjs/internal.cpp: (ContextImp::mark): Mark the scope chain.
* kjs/interpreter.cpp: (Context::scopeChain): Return chain by reference.
* kjs/interpreter.h: Make some Context methods inline.
* kjs/nodes.cpp:
(ThisNode::evaluate): Get at ContextImp directly.
(ResolveNode::evaluateReference): Ditto.
(VarDeclNode::evaluate): Ditto.
(VarDeclNode::processVarDecls): Ditto.
(FuncDeclNode::processFuncDecl): Pass ScopeChain directly to avoid copying.
(FuncExprNode::evaluate): Ditto.
* kjs/object.cpp: Make scope and setScope inline.
* kjs/object.h: Make scope return a chain by reference. Make scope and
setScope both be inline. Use a normal ScopeChain instead of NoRefScopeChain
since they are now one and the same.
* kjs/scope_chain.cpp: Remove all the code to ref and deref objects.
Merge NoRefScopeChain in with ScopeChain since they both work this way now.
* kjs/scope_chain.h: Remove NoRefScopeChain and simplify the ref counts.
Make more functions inline.
2002-11-24 Maciej Stachowiak <mjs@apple.com>
- fixed 3098356 - Hard hang on movie search at www.movietickets.com
......
2002-11-24 Darin Adler <darin@apple.com>
- changed ScopeChain to not ref each item in the chain, and use
marking instead; gains 1% on JavaScript iBench
* kjs/context.h: Return chain by reference.
* kjs/internal.cpp: (ContextImp::mark): Mark the scope chain.
* kjs/interpreter.cpp: (Context::scopeChain): Return chain by reference.
* kjs/interpreter.h: Make some Context methods inline.
* kjs/nodes.cpp:
(ThisNode::evaluate): Get at ContextImp directly.
(ResolveNode::evaluateReference): Ditto.
(VarDeclNode::evaluate): Ditto.
(VarDeclNode::processVarDecls): Ditto.
(FuncDeclNode::processFuncDecl): Pass ScopeChain directly to avoid copying.
(FuncExprNode::evaluate): Ditto.
* kjs/object.cpp: Make scope and setScope inline.
* kjs/object.h: Make scope return a chain by reference. Make scope and
setScope both be inline. Use a normal ScopeChain instead of NoRefScopeChain
since they are now one and the same.
* kjs/scope_chain.cpp: Remove all the code to ref and deref objects.
Merge NoRefScopeChain in with ScopeChain since they both work this way now.
* kjs/scope_chain.h: Remove NoRefScopeChain and simplify the ref counts.
Make more functions inline.
2002-11-24 Maciej Stachowiak <mjs@apple.com>
- fixed 3098356 - Hard hang on movie search at www.movietickets.com
......
2002-11-24 Darin Adler <darin@apple.com>
- changed ScopeChain to not ref each item in the chain, and use
marking instead; gains 1% on JavaScript iBench
* kjs/context.h: Return chain by reference.
* kjs/internal.cpp: (ContextImp::mark): Mark the scope chain.
* kjs/interpreter.cpp: (Context::scopeChain): Return chain by reference.
* kjs/interpreter.h: Make some Context methods inline.
* kjs/nodes.cpp:
(ThisNode::evaluate): Get at ContextImp directly.
(ResolveNode::evaluateReference): Ditto.
(VarDeclNode::evaluate): Ditto.
(VarDeclNode::processVarDecls): Ditto.
(FuncDeclNode::processFuncDecl): Pass ScopeChain directly to avoid copying.
(FuncExprNode::evaluate): Ditto.
* kjs/object.cpp: Make scope and setScope inline.
* kjs/object.h: Make scope return a chain by reference. Make scope and
setScope both be inline. Use a normal ScopeChain instead of NoRefScopeChain
since they are now one and the same.
* kjs/scope_chain.cpp: Remove all the code to ref and deref objects.
Merge NoRefScopeChain in with ScopeChain since they both work this way now.
* kjs/scope_chain.h: Remove NoRefScopeChain and simplify the ref counts.
Make more functions inline.
2002-11-24 Maciej Stachowiak <mjs@apple.com>
- fixed 3098356 - Hard hang on movie search at www.movietickets.com
......
......@@ -37,7 +37,7 @@ namespace KJS {
ContextImp *callingContext = 0, FunctionImp *functiion = 0, const List *args = 0);
~ContextImp();
const ScopeChain scopeChain() const { return scope; }
const ScopeChain &scopeChain() const { return scope; }
Object variableObject() const { return variable; }
void setVariableObject(const Object &v) { variable = v; }
Object thisValue() const { return thisVal; }
......
......@@ -413,6 +413,7 @@ ContextImp::~ContextImp()
void ContextImp::mark()
{
for (ContextImp *context = this; context; context = context->_callingContext) {
context->scope.mark();
context->_activationImp.mark();
#if DEBUG_COLLECTOR
context->_activationImp._flags &= ~ValueImp::VI_MARKED;
......
......@@ -41,37 +41,7 @@ using namespace KJS;
// ------------------------------ Context --------------------------------------
Context::Context(ContextImp *c)
{
rep = c;
}
Context::Context(const Context &c)
{
rep = c.rep;
}
Context& Context::operator=(const Context &c)
{
rep = c.rep;
return *this;
}
Context::~Context()
{
}
bool Context::isNull() const
{
return (rep == 0);
}
ContextImp *Context::imp() const
{
return rep;
}
const ScopeChain Context::scopeChain() const
const ScopeChain &Context::scopeChain() const
{
return rep->scopeChain();
}
......
......@@ -53,13 +53,9 @@ namespace KJS {
*/
class Context {
public:
Context(ContextImp *);
Context(const Context &c);
Context& operator=(const Context &c);
virtual ~Context();
Context(ContextImp *i) : rep(i) { }
bool isNull() const;
ContextImp *imp() const;
ContextImp *imp() const { return rep; }
/**
* Returns the scope chain for this execution context. This is used for
......@@ -68,7 +64,7 @@ namespace KJS {
*
* @return The execution context's scope chain
*/
const ScopeChain scopeChain() const;
const ScopeChain &scopeChain() const;
/**
* Returns the variable object for the execution context. This contains a
......@@ -104,6 +100,7 @@ namespace KJS {
* @return The calling execution context
*/
const Context callingContext() const;
private:
ContextImp *rep;
};
......@@ -379,7 +376,7 @@ namespace KJS {
*
* @return The current execution state context
*/
const Context context() const { return _context; }
Context context() const { return _context; }
void setException(const Value &e) { _exception = e; }
void clearException() { _exception = Value(); }
......
......@@ -205,7 +205,7 @@ Value RegExpNode::evaluate(ExecState *exec)
// ECMA 11.1.1
Value ThisNode::evaluate(ExecState *exec)
{
return exec->context().thisValue();
return exec->context().imp()->thisValue();
}
// ------------------------------ ResolveNode ----------------------------------
......@@ -218,7 +218,7 @@ Value ResolveNode::evaluate(ExecState *exec)
Reference ResolveNode::evaluateReference(ExecState *exec)
{
ScopeChain chain = exec->context().scopeChain();
ScopeChain chain = exec->context().imp()->scopeChain();
while (!chain.isEmpty()) {
ObjectImp *o = chain.top();
......@@ -1632,7 +1632,7 @@ bool VarDeclNode::deref()
// ECMA 12.2
Value VarDeclNode::evaluate(ExecState *exec)
{
Object variable = Object::dynamicCast(exec->context().variableObject());
Object variable = Object::dynamicCast(exec->context().imp()->variableObject());
Value val;
if (init) {
......@@ -1656,7 +1656,7 @@ Value VarDeclNode::evaluate(ExecState *exec)
void VarDeclNode::processVarDecls(ExecState *exec)
{
Object variable = exec->context().variableObject();
Object variable = exec->context().imp()->variableObject();
variable.put(exec,ident, Undefined(), DontDelete);
}
......@@ -2779,10 +2779,8 @@ bool FuncDeclNode::deref()
// ECMA 13
void FuncDeclNode::processFuncDecl(ExecState *exec)
{
const ScopeChain sc = exec->context().imp()->scopeChain();
// TODO: let this be an object with [[Class]] property "Function"
FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, sc);
FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
Object func(fimp); // protect from GC
// Value proto = exec->interpreter()->builtinObject().construct(exec,List::empty());
......@@ -2834,8 +2832,7 @@ bool FuncExprNode::deref()
// ECMA 13
Value FuncExprNode::evaluate(ExecState *exec)
{
const ScopeChain sc = exec->context().scopeChain();
FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null, body, sc);
FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null, body, exec->context().imp()->scopeChain());
Value ret(fimp);
List empty;
Value proto = exec->interpreter()->builtinObject().construct(exec,empty);
......
......@@ -364,16 +364,6 @@ Boolean ObjectImp::hasInstance(ExecState */*exec*/, const Value &/*value*/)
return Boolean(false);
}
const ScopeChain ObjectImp::scope() const
{
return _scope;
}
void ObjectImp::setScope(const ScopeChain &s)
{
_scope = s;
}
ReferenceList ObjectImp::propList(ExecState *exec, bool recursive)
{
ReferenceList list;
......
......@@ -319,7 +319,7 @@ namespace KJS {
* @param exec The current execution state
* @return The function's scope
*/
const ScopeChain scope() const;
const ScopeChain &scope() const;
void setScope(const ScopeChain &s);
/**
......@@ -569,8 +569,8 @@ namespace KJS {
*
* @see Object::scope()
*/
const ScopeChain scope() const;
void setScope(const ScopeChain &s);
const ScopeChain &scope() const { return _scope; }
void setScope(const ScopeChain &s) { _scope = s; }
ReferenceList propList(ExecState *exec, bool recursive = true);
......@@ -603,7 +603,7 @@ namespace KJS {
const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const;
ValueImp *_proto;
ValueImp *_internalValue;
NoRefScopeChain _scope;
ScopeChain _scope;
};
/**
......@@ -706,7 +706,7 @@ namespace KJS {
inline Boolean Object::hasInstance(ExecState *exec, const Value &value)
{ return imp()->hasInstance(exec,value); }
inline const ScopeChain Object::scope() const
inline const ScopeChain &Object::scope() const
{ return imp()->scope(); }
inline void Object::setScope(const ScopeChain &s)
......
......@@ -25,27 +25,14 @@
namespace KJS {
ScopeChainNode::ScopeChainNode(ScopeChainNode *n, ObjectImp *o)
: next(n), object(o), nodeAndObjectRefCount(1), nodeOnlyRefCount(0)
{
o->ref();
}
inline void ScopeChain::ref() const
{
for (ScopeChainNode *n = _node; n; n = n->next) {
if (n->nodeAndObjectRefCount++ != 0)
if (n->refCount++ != 0)
break;
n->object->ref();
}
}
ScopeChain::ScopeChain(const NoRefScopeChain &c)
: _node(c._node)
{
ref();
}
ScopeChain &ScopeChain::operator=(const ScopeChain &c)
{
c.ref();
......@@ -66,20 +53,11 @@ void ScopeChain::pop()
ScopeChainNode *newNode = oldNode->next;
_node = newNode;
// Three cases:
// 1) This was not the last reference of the old node.
// In this case we move our ref from the old to the new node.
// 2) This was the last reference of the old node, but there are garbage collected references.
// In this case, the new node doesn't get any new ref, and the object is deref'd.
// 3) This was the last reference of the old node.
// In this case the object is deref'd and the entire node goes.
if (--oldNode->nodeAndObjectRefCount != 0) {
if (--oldNode->refCount != 0) {
if (newNode)
++newNode->nodeAndObjectRefCount;
++newNode->refCount;
} else {
oldNode->object->deref();
if (oldNode->nodeOnlyRefCount == 0)
delete oldNode;
delete oldNode;
}
}
......@@ -88,29 +66,12 @@ void ScopeChain::release()
ScopeChainNode *n = _node;
do {
ScopeChainNode *next = n->next;
n->object->deref();
if (n->nodeOnlyRefCount == 0)
delete n;
delete n;
n = next;
} while (n && --n->nodeAndObjectRefCount == 0);
}
inline void NoRefScopeChain::ref() const
{
for (ScopeChainNode *n = _node; n; n = n->next)
if (n->nodeOnlyRefCount++ != 0)
break;
}
NoRefScopeChain &NoRefScopeChain::operator=(const ScopeChain &c)
{
c.ref();
deref();
_node = c._node;
return *this;
} while (n && --n->refCount == 0);
}
void NoRefScopeChain::mark()
void ScopeChain::mark()
{
for (ScopeChainNode *n = _node; n; n = n->next) {
ObjectImp *o = n->object;
......@@ -119,15 +80,4 @@ void NoRefScopeChain::mark()
}
}
void NoRefScopeChain::release()
{
ScopeChainNode *n = _node;
do {
ScopeChainNode *next = n->next;
if (n->nodeAndObjectRefCount == 0)
delete n;
n = next;
} while (n && --n->nodeOnlyRefCount == 0);
}
} // namespace KJS
......@@ -24,28 +24,25 @@
namespace KJS {
class NoRefScopeChain;
class ObjectImp;
class ScopeChainNode {
public:
ScopeChainNode(ScopeChainNode *n, ObjectImp *o);
ScopeChainNode(ScopeChainNode *n, ObjectImp *o)
: next(n), object(o), refCount(1) { }
ScopeChainNode *next;
ObjectImp *object;
short nodeAndObjectRefCount;
short nodeOnlyRefCount;
int refCount;
};
class ScopeChain {
friend class NoRefScopeChain;
public:
ScopeChain() : _node(0) { }
~ScopeChain() { deref(); }
ScopeChain(const ScopeChain &c) : _node(c._node)
{ if (_node) ++_node->nodeAndObjectRefCount; }
ScopeChain(const NoRefScopeChain &);
{ if (_node) ++_node->refCount; }
ScopeChain &operator=(const ScopeChain &);
bool isEmpty() const { return !_node; }
......@@ -55,35 +52,15 @@ namespace KJS {
void push(ObjectImp *);
void pop();
private:
ScopeChainNode *_node;
void deref() { if (_node && --_node->nodeAndObjectRefCount == 0) release(); }
void ref() const;
void release();
};
class NoRefScopeChain {
friend class ScopeChain;
public:
NoRefScopeChain() : _node(0) { }
~NoRefScopeChain() { deref(); }
NoRefScopeChain &operator=(const ScopeChain &c);
void mark();
private:
ScopeChainNode *_node;
void deref() { if (_node && --_node->nodeOnlyRefCount == 0) release(); }
void deref() { if (_node && --_node->refCount == 0) release(); }
void ref() const;
void release();
NoRefScopeChain(const NoRefScopeChain &);
NoRefScopeChain &operator=(const NoRefScopeChain &);
};
}; // namespace KJS
......
2002-11-24 Darin Adler <darin@apple.com>
* force-js-clean-timestamp: Touch for ScopeChain change.
2002-11-24 Maciej Stachowiak <mjs@apple.com>
- fixed 3067939 - no support for window.document.lastModified
......
2002-11-24 Darin Adler <darin@apple.com>
* force-js-clean-timestamp: Touch for ScopeChain change.
2002-11-24 Maciej Stachowiak <mjs@apple.com>
- fixed 3067939 - no support for window.document.lastModified
......
2002-11-24 Darin Adler <darin@apple.com>
* force-js-clean-timestamp: Touch for ScopeChain change.
2002-11-24 Maciej Stachowiak <mjs@apple.com>
- fixed 3067939 - no support for window.document.lastModified
......
List 11/22 - Darin
ScopeChain inlining 11/24 - Darin
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