[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

darin darin at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:06:37 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 7b978750ac46c5e87b79c81ba642a281301e30ce
Author: darin <darin at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Nov 22 09:04:55 2002 +0000

    JavaScriptCore:
    
    	- change ScopeChain to be a singly linked list shares tails, gives 11% gain on iBench
    
            * kjs/context.h:
            (ContextImp::pushScope): Make inline, use push instead of prepend, and pass imp pointer.
            (ContextImp::popScope): Make inline, use pop instead of removeFirst.
            * kjs/function.cpp: (DeclaredFunctionImp::DeclaredFunctionImp): No need to copy.
            * kjs/function_object.cpp: (FunctionObjectImp::construct): Use push instead of
    	prepend, and pass imp pointer.
            * kjs/internal.cpp: (ContextImp::ContextImp): Use clear, push instead of prepend,
    	and pass imp pointers.
            * kjs/nodes.cpp: (ResolveNode::evaluateReference): Use isEmpty, pop, and top instead
    	of ScopeChainIterator.
            * kjs/object.h: Change _scope to be a NoRefScopeChain.
            * kjs/object.cpp: No need to initialize _scope any more, since it's not a NoRefScopeChain.
    
            * kjs/scope_chain.h: Rewrite, different implementation and interface.
            * kjs/scope_chain.cpp: More of the same.
    
    WebCore:
    
            * khtml/ecma/kjs_dom.cpp: (DOMNode::pushEventHandlerScope): Change to push handlers
    	on an existing scope chain rather than returning one. Name change too.
            * khtml/ecma/kjs_dom.h: More of the same.
            * khtml/ecma/kjs_html.cpp: (KJS::HTMLElement::pushEventHandlerScope): And here.
            * khtml/ecma/kjs_html.h: And here.
    
            * khtml/ecma/kjs_events.cpp: (JSEventListener::handleEvent): Use the pushEventHandlerScope
    	function, and also don't worry about optimizing the "no change" case, because that already
    	works pretty efficiently.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2824 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 56c82a7..fb72c15 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,23 @@
+2002-11-22  Darin Adler  <darin at apple.com>
+
+	- change ScopeChain to be a singly linked list shares tails, gives 11% gain on iBench
+
+        * kjs/context.h:
+        (ContextImp::pushScope): Make inline, use push instead of prepend, and pass imp pointer.
+        (ContextImp::popScope): Make inline, use pop instead of removeFirst.
+        * kjs/function.cpp: (DeclaredFunctionImp::DeclaredFunctionImp): No need to copy.
+        * kjs/function_object.cpp: (FunctionObjectImp::construct): Use push instead of
+	prepend, and pass imp pointer.
+        * kjs/internal.cpp: (ContextImp::ContextImp): Use clear, push instead of prepend,
+	and pass imp pointers.
+        * kjs/nodes.cpp: (ResolveNode::evaluateReference): Use isEmpty, pop, and top instead
+	of ScopeChainIterator.
+        * kjs/object.h: Change _scope to be a NoRefScopeChain.
+        * kjs/object.cpp: No need to initialize _scope any more, since it's not a NoRefScopeChain.
+
+        * kjs/scope_chain.h: Rewrite, different implementation and interface.
+        * kjs/scope_chain.cpp: More of the same.
+
 2002-11-22  Maciej Stachowiak  <mjs at apple.com>
 
 	- a simple change for .5% gain on ibench - instead of unmarking
diff --git a/JavaScriptCore/ChangeLog-2002-12-03 b/JavaScriptCore/ChangeLog-2002-12-03
index 56c82a7..fb72c15 100644
--- a/JavaScriptCore/ChangeLog-2002-12-03
+++ b/JavaScriptCore/ChangeLog-2002-12-03
@@ -1,3 +1,23 @@
+2002-11-22  Darin Adler  <darin at apple.com>
+
+	- change ScopeChain to be a singly linked list shares tails, gives 11% gain on iBench
+
+        * kjs/context.h:
+        (ContextImp::pushScope): Make inline, use push instead of prepend, and pass imp pointer.
+        (ContextImp::popScope): Make inline, use pop instead of removeFirst.
+        * kjs/function.cpp: (DeclaredFunctionImp::DeclaredFunctionImp): No need to copy.
+        * kjs/function_object.cpp: (FunctionObjectImp::construct): Use push instead of
+	prepend, and pass imp pointer.
+        * kjs/internal.cpp: (ContextImp::ContextImp): Use clear, push instead of prepend,
+	and pass imp pointers.
+        * kjs/nodes.cpp: (ResolveNode::evaluateReference): Use isEmpty, pop, and top instead
+	of ScopeChainIterator.
+        * kjs/object.h: Change _scope to be a NoRefScopeChain.
+        * kjs/object.cpp: No need to initialize _scope any more, since it's not a NoRefScopeChain.
+
+        * kjs/scope_chain.h: Rewrite, different implementation and interface.
+        * kjs/scope_chain.cpp: More of the same.
+
 2002-11-22  Maciej Stachowiak  <mjs at apple.com>
 
 	- a simple change for .5% gain on ibench - instead of unmarking
diff --git a/JavaScriptCore/ChangeLog-2003-10-25 b/JavaScriptCore/ChangeLog-2003-10-25
index 56c82a7..fb72c15 100644
--- a/JavaScriptCore/ChangeLog-2003-10-25
+++ b/JavaScriptCore/ChangeLog-2003-10-25
@@ -1,3 +1,23 @@
+2002-11-22  Darin Adler  <darin at apple.com>
+
+	- change ScopeChain to be a singly linked list shares tails, gives 11% gain on iBench
+
+        * kjs/context.h:
+        (ContextImp::pushScope): Make inline, use push instead of prepend, and pass imp pointer.
+        (ContextImp::popScope): Make inline, use pop instead of removeFirst.
+        * kjs/function.cpp: (DeclaredFunctionImp::DeclaredFunctionImp): No need to copy.
+        * kjs/function_object.cpp: (FunctionObjectImp::construct): Use push instead of
+	prepend, and pass imp pointer.
+        * kjs/internal.cpp: (ContextImp::ContextImp): Use clear, push instead of prepend,
+	and pass imp pointers.
+        * kjs/nodes.cpp: (ResolveNode::evaluateReference): Use isEmpty, pop, and top instead
+	of ScopeChainIterator.
+        * kjs/object.h: Change _scope to be a NoRefScopeChain.
+        * kjs/object.cpp: No need to initialize _scope any more, since it's not a NoRefScopeChain.
+
+        * kjs/scope_chain.h: Rewrite, different implementation and interface.
+        * kjs/scope_chain.cpp: More of the same.
+
 2002-11-22  Maciej Stachowiak  <mjs at apple.com>
 
 	- a simple change for .5% gain on ibench - instead of unmarking
diff --git a/JavaScriptCore/kjs/context.h b/JavaScriptCore/kjs/context.h
index 5e0be1f..880b447 100644
--- a/JavaScriptCore/kjs/context.h
+++ b/JavaScriptCore/kjs/context.h
@@ -46,8 +46,8 @@ namespace KJS  {
     FunctionImp *function() const { return _function; }
     const List *arguments() const { return _arguments; }
 
-    void pushScope(const Object &s);
-    void popScope();
+    void pushScope(const Object &s) { scope.push(s.imp()); }
+    void popScope() { scope.pop(); }
     LabelStack *seenLabels() { return &ls; }
     
     void mark();
diff --git a/JavaScriptCore/kjs/function.cpp b/JavaScriptCore/kjs/function.cpp
index 7315a5a..b95ba8a 100644
--- a/JavaScriptCore/kjs/function.cpp
+++ b/JavaScriptCore/kjs/function.cpp
@@ -260,7 +260,7 @@ DeclaredFunctionImp::DeclaredFunctionImp(ExecState *exec, const Identifier &n,
 {
   Value protect(this);
   body->ref();
-  setScope(sc.copy());
+  setScope(sc);
 }
 
 DeclaredFunctionImp::~DeclaredFunctionImp()
diff --git a/JavaScriptCore/kjs/function_object.cpp b/JavaScriptCore/kjs/function_object.cpp
index 826e5e0..fc63137 100644
--- a/JavaScriptCore/kjs/function_object.cpp
+++ b/JavaScriptCore/kjs/function_object.cpp
@@ -234,7 +234,7 @@ Object FunctionObjectImp::construct(ExecState *exec, const List &args)
   }
 
   ScopeChain scopeChain;
-  scopeChain.prepend(exec->interpreter()->globalObject());
+  scopeChain.push(exec->interpreter()->globalObject().imp());
   FunctionBodyNode *bodyNode = progNode;
 
   FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null, bodyNode,
diff --git a/JavaScriptCore/kjs/internal.cpp b/JavaScriptCore/kjs/internal.cpp
index a84b747..c930558 100644
--- a/JavaScriptCore/kjs/internal.cpp
+++ b/JavaScriptCore/kjs/internal.cpp
@@ -377,25 +377,25 @@ ContextImp::ContextImp(Object &glob, InterpreterImp *interpreter, Object &thisV,
   switch(type) {
     case EvalCode:
       if (_callingContext) {
-	scope = _callingContext->scopeChain().copy();
+	scope = _callingContext->scopeChain();
 	variable = _callingContext->variableObject();
 	thisVal = _callingContext->thisValue();
 	break;
       } // else same as GlobalCode
     case GlobalCode:
-      scope = ScopeChain();
-      scope.prepend(glob);
+      scope.clear();
+      scope.push(glob.imp());
       thisVal = Object(static_cast<ObjectImp*>(glob.imp()));
       break;
     case FunctionCode:
     case AnonymousCode:
       if (type == FunctionCode) {
-	scope = func->scope().copy();
-	scope.prepend(activation);
+	scope = func->scope();
+	scope.push(activation.imp());
       } else {
-	scope = ScopeChain();
-	scope.prepend(glob);
-	scope.prepend(activation);
+	scope.clear();
+	scope.push(glob.imp());
+	scope.push(activation.imp());
       }
       variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
       thisVal = thisV;
@@ -410,16 +410,6 @@ ContextImp::~ContextImp()
   _interpreter->setContext(_callingContext);
 }
 
-void ContextImp::pushScope(const Object &s)
-{
-  scope.prepend(s);
-}
-
-void ContextImp::popScope()
-{
-  scope.removeFirst();
-}
-
 void ContextImp::mark()
 {
   for (ContextImp *context = this; context; context = context->_callingContext)
diff --git a/JavaScriptCore/kjs/nodes.cpp b/JavaScriptCore/kjs/nodes.cpp
index 5e4949e..4d5d453 100644
--- a/JavaScriptCore/kjs/nodes.cpp
+++ b/JavaScriptCore/kjs/nodes.cpp
@@ -218,11 +218,10 @@ Value ResolveNode::evaluate(ExecState *exec)
 
 Reference ResolveNode::evaluateReference(ExecState *exec)
 {
-  const ScopeChain chain = exec->context().scopeChain();
-  ScopeChainIterator scope = chain.begin();
+  ScopeChain chain = exec->context().scopeChain();
 
-  while (scope != chain.end()) {
-    ObjectImp *o = static_cast<ObjectImp*>((*scope).imp());
+  while (!chain.isEmpty()) {
+    ObjectImp *o = chain.top();
 
     //cout << "Resolve: looking at '" << ident.ascii() << "'"
     //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
@@ -231,7 +230,8 @@ Reference ResolveNode::evaluateReference(ExecState *exec)
       //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
       return Reference(o, ident);
     }
-    scope++;
+    
+    chain.pop();
   }
 
   // identifier not found
diff --git a/JavaScriptCore/kjs/object.cpp b/JavaScriptCore/kjs/object.cpp
index b6dd5a2..1d514a7 100644
--- a/JavaScriptCore/kjs/object.cpp
+++ b/JavaScriptCore/kjs/object.cpp
@@ -53,19 +53,18 @@ Object Object::dynamicCast(const Value &v)
 // ------------------------------ ObjectImp ------------------------------------
 
 ObjectImp::ObjectImp(const Object &proto)
-  : _proto(static_cast<ObjectImp*>(proto.imp())), _internalValue(0L), _scope(true)
+  : _proto(static_cast<ObjectImp*>(proto.imp())), _internalValue(0L)
 {
   //fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
 }
 
 ObjectImp::ObjectImp(ObjectImp *proto)
-  : _proto(proto), _internalValue(0L), _scope(true)
+  : _proto(proto), _internalValue(0L)
 {
   //fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
 }
 
-ObjectImp::ObjectImp() :
-  _scope(true)
+ObjectImp::ObjectImp()
 {
   //fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
   _proto = NullImp::staticNull;
diff --git a/JavaScriptCore/kjs/object.h b/JavaScriptCore/kjs/object.h
index 05c5155..69d78d0 100644
--- a/JavaScriptCore/kjs/object.h
+++ b/JavaScriptCore/kjs/object.h
@@ -602,7 +602,7 @@ namespace KJS {
     PropertyMap _prop;
     ValueImp *_proto;
     ValueImp *_internalValue;
-    ScopeChain _scope;
+    NoRefScopeChain _scope;
   };
 
   /**
diff --git a/JavaScriptCore/kjs/scope_chain.cpp b/JavaScriptCore/kjs/scope_chain.cpp
index c3fd770..a9ec527 100644
--- a/JavaScriptCore/kjs/scope_chain.cpp
+++ b/JavaScriptCore/kjs/scope_chain.cpp
@@ -1,8 +1,6 @@
-// -*- c-basic-offset: 2 -*-
 /*
  *  This file is part of the KDE libraries
- *  Copyright (C) 1999-2001 Harri Porten (porten at kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk at post.com)
+ *  Copyright (C) 2002 Apple Computer, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -23,209 +21,113 @@
 
 #include "scope_chain.h"
 
-namespace KJS {
-
-  struct ScopeChainNode {
-    ScopeChainNode(const Value &val, ScopeChainNode *p, ScopeChainNode *n)
-      : member(val.imp()), prev(p), next(n) { }
-    ScopeChainNode(ValueImp *val, ScopeChainNode *p, ScopeChainNode *n)
-      : member(val), prev(p), next(n) { }
-    ValueImp *member;
-    ScopeChainNode *prev, *next;
-  };
-
-  struct ScopeChainHookNode : public ScopeChainNode {
-    ScopeChainHookNode(bool needsMarking) : ScopeChainNode(Value(), this, this),
-        listRefCount(1), nodesRefCount(needsMarking ? 0 : 1) { }
-    int listRefCount;
-    int nodesRefCount;
-  };
-
-// ------------------------------ ScopeChainIterator ---------------------------------
-
-ValueImp* ScopeChainIterator::operator->() const
-{
-  return node->member;
-}
-
-Value ScopeChainIterator::operator*() const
-{
-  return Value(node->member);
-}
-
-Value ScopeChainIterator::operator++()
-{
-  node = node->next;
-  return Value(node->member);
-}
-
-Value ScopeChainIterator::operator++(int)
-{
-  const ScopeChainNode *n = node;
-  ++*this;
-  return Value(n->member);
-}
-
-// ------------------------------ ScopeChain -----------------------------------------
-
-ScopeChain::ScopeChain(bool needsMarking) : hook(new ScopeChainHookNode(needsMarking)), m_needsMarking(needsMarking)
-{
-}
-
-ScopeChain::ScopeChain(const ScopeChain& l) : hook(l.hook), m_needsMarking(false)
-{
-  ++hook->listRefCount;
-  if (hook->nodesRefCount++ == 0)
-    refAll();
-}
-
-ScopeChain& ScopeChain::operator=(const ScopeChain& l)
-{
-  ScopeChain(l).swap(*this);
-  return *this;
-}
-
-ScopeChain::~ScopeChain()
-{
-  if (!m_needsMarking)
-    if (--hook->nodesRefCount == 0)
-      derefAll();
-  
-  if (--hook->listRefCount == 0) {
-    assert(hook->nodesRefCount == 0);
-    clearInternal();
-    delete hook;
-  }
-}
-
-void ScopeChain::mark() const
-{
-  ScopeChainNode *n = hook->next;
-  while (n != hook) {
-    if (!n->member->marked())
-      n->member->mark();
-    n = n->next;
-  }
-}
-
-void ScopeChain::append(const Value& val)
-{
-  ScopeChainNode *n = new ScopeChainNode(val, hook->prev, hook);
-  if (hook->nodesRefCount)
-    n->member->ref();
-  hook->prev->next = n;
-  hook->prev = n;
-}
-
-void ScopeChain::prepend(const Value& val)
-{
-  ScopeChainNode *n = new ScopeChainNode(val, hook, hook->next);
-  if (hook->nodesRefCount)
-    n->member->ref();
-  hook->next->prev = n;
-  hook->next = n;
-}
+#include "object.h"
 
-void ScopeChain::prepend(ValueImp *val)
-{
-  ScopeChainNode *n = new ScopeChainNode(val, hook, hook->next);
-  if (hook->nodesRefCount)
-    n->member->ref();
-  hook->next->prev = n;
-  hook->next = n;
-}
+namespace KJS {
 
-void ScopeChain::prependList(const ScopeChain& lst)
+ScopeChainNode::ScopeChainNode(ScopeChainNode *n, ObjectImp *o)
+    : next(n), object(o), nodeAndObjectRefCount(1), nodeOnlyRefCount(0)
 {
-  ScopeChainNode *otherHook = lst.hook;
-  ScopeChainNode *n = otherHook->prev;
-  while (n != otherHook) {
-    prepend(n->member);
-    n = n->prev;
-  }
+    o->ref();
 }
 
-void ScopeChain::removeFirst()
+inline void ScopeChain::ref() const
 {
-  erase(hook->next);
+    for (ScopeChainNode *n = _node; n; n = n->next) {
+        if (n->nodeAndObjectRefCount++ != 0)
+            break;
+        n->object->ref();
+    }
 }
 
-void ScopeChain::clearInternal()
+ScopeChain::ScopeChain(const NoRefScopeChain &c)
+    : _node(c._node)
 {
-  ScopeChainNode *n = hook->next;
-  while (n != hook) {
-    n = n->next;
-    delete n->prev;
-  }
-
-  hook->next = hook;
-  hook->prev = hook;
+    ref();
 }
 
-ScopeChain ScopeChain::copy() const
+ScopeChain &ScopeChain::operator=(const ScopeChain &c)
 {
-  ScopeChain newScopeChain;
-  newScopeChain.prependList(*this);
-  return newScopeChain;
+    c.ref();
+    deref();
+    _node = c._node;
+    return *this;
 }
 
-ScopeChainIterator ScopeChain::begin() const
+void ScopeChain::push(ObjectImp *o)
 {
-  return ScopeChainIterator(hook->next);
+    _node = new ScopeChainNode(_node, o);
 }
 
-ScopeChainIterator ScopeChain::end() const
+void ScopeChain::pop()
 {
-  return ScopeChainIterator(hook);
+    ScopeChainNode *oldNode = _node;
+    assert(oldNode);
+    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 (newNode)
+            ++newNode->nodeAndObjectRefCount;
+    } else {
+        oldNode->object->deref();
+        if (oldNode->nodeOnlyRefCount == 0)
+            delete oldNode;
+    }
 }
 
-void ScopeChain::erase(ScopeChainNode *n)
+void ScopeChain::release()
 {
-  if (n != hook) {
-    if (hook->nodesRefCount)
-      n->member->deref();
-    n->next->prev = n->prev;
-    n->prev->next = n->next;
-    delete n;
-  }
+    ScopeChainNode *n = _node;
+    do {
+        ScopeChainNode *next = n->next;
+        n->object->deref();
+        if (n->nodeOnlyRefCount == 0)
+            delete n;
+        n = next;
+    } while (n && --n->nodeAndObjectRefCount == 0);
 }
 
-void ScopeChain::refAll() const
+inline void NoRefScopeChain::ref() const
 {
-  for (ScopeChainNode *n = hook->next; n != hook; n = n->next)
-    n->member->ref();
+    for (ScopeChainNode *n = _node; n; n = n->next)
+        if (n->nodeOnlyRefCount++ != 0)
+            break;
 }
 
-void ScopeChain::derefAll() const
+NoRefScopeChain &NoRefScopeChain::operator=(const ScopeChain &c)
 {
-  for (ScopeChainNode *n = hook->next; n != hook; n = n->next)
-    n->member->deref();
+    c.ref();
+    deref();
+    _node = c._node;
+    return *this;
 }
 
-void ScopeChain::swap(ScopeChain &other)
+void NoRefScopeChain::mark()
 {
-  if (!m_needsMarking)
-    if (other.hook->nodesRefCount++ == 0)
-      other.refAll();
-  if (!other.m_needsMarking)
-    if (hook->nodesRefCount++ == 0)
-      refAll();
-
-  if (!m_needsMarking)
-    if (--hook->nodesRefCount == 0)
-      derefAll();
-  if (!other.m_needsMarking)
-    if (--other.hook->nodesRefCount == 0)
-      other.derefAll();
-
-  ScopeChainHookNode *tmp = hook;
-  hook = other.hook;
-  other.hook = tmp;
+    for (ScopeChainNode *n = _node; n; n = n->next) {
+        ObjectImp *o = n->object;
+        if (!o->marked())
+            o->mark();
+    }
 }
 
-bool ScopeChain::isEmpty() const
+void NoRefScopeChain::release()
 {
-    return hook->next == hook;
+    ScopeChainNode *n = _node;
+    do {
+        ScopeChainNode *next = n->next;
+        if (n->nodeAndObjectRefCount == 0)
+            delete n;
+        n = next;
+    } while (n && --n->nodeOnlyRefCount == 0);
 }
 
 } // namespace KJS
diff --git a/JavaScriptCore/kjs/scope_chain.h b/JavaScriptCore/kjs/scope_chain.h
index 469eb17..bd7d5d7 100644
--- a/JavaScriptCore/kjs/scope_chain.h
+++ b/JavaScriptCore/kjs/scope_chain.h
@@ -1,8 +1,6 @@
-// -*- c-basic-offset: 2 -*-
 /*
  *  This file is part of the KDE libraries
- *  Copyright (C) 1999-2001 Harri Porten (porten at kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk at post.com)
+ *  Copyright (C) 2002 Apple Computer, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -24,124 +22,70 @@
 #ifndef KJS_SCOPE_CHAIN_H
 #define KJS_SCOPE_CHAIN_H
 
-#include "value.h"
-
-// internal data types
-
 namespace KJS {
 
-  class ScopeChain;
-  class ScopeChainIterator;
-  class ScopeChainNode;
-  class ScopeChainHookNode;
-
-  /**
-   * @short Iterator for @ref KJS::ScopeChain objects.
-   */
-  class ScopeChainIterator {
-    friend class ScopeChain;
-    ScopeChainIterator() : node(0) { }
-    ScopeChainIterator(ScopeChainNode *n) : node(n) { }
-  public:
-    /**
-     * Construct an iterator that points to the first element of the list.
-     * @param l The list the iterator will operate on.
-     */
-    ScopeChainIterator(const ScopeChain &l);
-    /**
-     * Dereference the iterator.
-     * @return A pointer to the element the iterator operates on.
-     */
-    ValueImp* operator->() const;
-    Value operator*() const;
-    /**
-     * Postfix increment operator.
-     * @return The element after the increment.
-     */
-    Value operator++();
-    /**
-     * Prefix increment operator.
-     */
-    Value operator++(int);
-    /**
-     * Compare the iterator with another one.
-     * @return True if the two iterators operate on the same list element.
-     * False otherwise.
-     */
-    bool operator==(const ScopeChainIterator &it) const { return node == it.node; }
-    /**
-     * Check for inequality with another iterator.
-     * @return True if the two iterators operate on different list elements.
-     */
-    bool operator!=(const ScopeChainIterator &it) const { return node != it.node; }
-  private:
-    ScopeChainNode *node;
-  };
-
-  /**
-   * @short Native list type.
-   *
-   * ScopeChain is a native ECMAScript type. ScopeChain values are only used for
-   * intermediate results of expression evaluation and cannot be stored
-   * as properties of objects.
-   *
-   * The list is explicitly shared. Note that while copy() returns a
-   * copy of the list the referenced objects are still shared.
-   */
-  class ScopeChain {
-    friend class ScopeChainIterator;
-  public:
-    ScopeChain(bool needsMarking = false);
-    ScopeChain(const ScopeChain& l);
-    ScopeChain &operator=(const ScopeChain& l);
-
-    ~ScopeChain();
-
-    /**
-     * Insert an object at the beginning of the list.
-     *
-     * @param val Pointer to object.
-     */
-    void prepend(const Value& val);
-    /**
-     * Remove the element at the beginning of the list.
-     */
-    void removeFirst();
-    /**
-     * Returns a shallow copy of the list. Ownership is passed to the user
-     * who is responsible for deleting the list then.
-     */
-    ScopeChain copy() const;
-    /**
-     * @return A @ref KJS::ScopeChainIterator pointing to the first element.
-     */
-    ScopeChainIterator begin() const;
-    /**
-     * @return A @ref KJS::ScopeChainIterator pointing to the last element.
-     */
-    ScopeChainIterator end() const;
-
-    bool isEmpty() const;
+    class NoRefScopeChain;
+    class ObjectImp;
     
-    void mark() const;
+    class ScopeChainNode {
+    public:
+        ScopeChainNode(ScopeChainNode *n, ObjectImp *o);
 
-    // temporary
-    void prependList(const ScopeChain &);
-    void append(const Value &);
+        ScopeChainNode *next;
+        ObjectImp *object;
+        short nodeAndObjectRefCount;
+        short nodeOnlyRefCount;
+    };
 
-  private:
+    class ScopeChain {
+        friend class NoRefScopeChain;
+    public:
+        ScopeChain() : _node(0) { }
+        ~ScopeChain() { deref(); }
 
-    void prepend(ValueImp *val);
-    void erase(ScopeChainNode *n);
-    void clearInternal();
-    void refAll() const;
-    void derefAll() const;
-    void swap(ScopeChain &other);
-    
-    ScopeChainHookNode *hook;
-    bool m_needsMarking;
-  };
-  
-}; // namespace
+        ScopeChain(const ScopeChain &c) : _node(c._node)
+            { if (_node) ++_node->nodeAndObjectRefCount; }
+        ScopeChain(const NoRefScopeChain &);
+        ScopeChain &operator=(const ScopeChain &);
+
+        bool isEmpty() const { return !_node; }
+        ObjectImp *top() const { return _node->object; }
+
+        void clear() { deref(); _node = 0; }
+        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 ref() const;
+
+        void release();
+
+        NoRefScopeChain(const NoRefScopeChain &);
+        NoRefScopeChain &operator=(const NoRefScopeChain &);
+    };
+
+}; // namespace KJS
 
 #endif // KJS_SCOPE_CHAIN_H
diff --git a/WebCore/ChangeLog-2002-12-03 b/WebCore/ChangeLog-2002-12-03
index 8bae0fb..2732b69 100644
--- a/WebCore/ChangeLog-2002-12-03
+++ b/WebCore/ChangeLog-2002-12-03
@@ -1,3 +1,15 @@
+2002-11-22  Darin Adler  <darin at apple.com>
+
+        * khtml/ecma/kjs_dom.cpp: (DOMNode::pushEventHandlerScope): Change to push handlers
+	on an existing scope chain rather than returning one. Name change too.
+        * khtml/ecma/kjs_dom.h: More of the same.
+        * khtml/ecma/kjs_html.cpp: (KJS::HTMLElement::pushEventHandlerScope): And here.
+        * khtml/ecma/kjs_html.h: And here.
+
+        * khtml/ecma/kjs_events.cpp: (JSEventListener::handleEvent): Use the pushEventHandlerScope
+	function, and also don't worry about optimizing the "no change" case, because that already
+	works pretty efficiently.
+
 2002-11-22  David Hyatt  <hyatt at apple.com>
 
 	Fix for the weather.com, slate and espn malformations that
diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index 8bae0fb..2732b69 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,15 @@
+2002-11-22  Darin Adler  <darin at apple.com>
+
+        * khtml/ecma/kjs_dom.cpp: (DOMNode::pushEventHandlerScope): Change to push handlers
+	on an existing scope chain rather than returning one. Name change too.
+        * khtml/ecma/kjs_dom.h: More of the same.
+        * khtml/ecma/kjs_html.cpp: (KJS::HTMLElement::pushEventHandlerScope): And here.
+        * khtml/ecma/kjs_html.h: And here.
+
+        * khtml/ecma/kjs_events.cpp: (JSEventListener::handleEvent): Use the pushEventHandlerScope
+	function, and also don't worry about optimizing the "no change" case, because that already
+	works pretty efficiently.
+
 2002-11-22  David Hyatt  <hyatt at apple.com>
 
 	Fix for the weather.com, slate and espn malformations that
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 8bae0fb..2732b69 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,15 @@
+2002-11-22  Darin Adler  <darin at apple.com>
+
+        * khtml/ecma/kjs_dom.cpp: (DOMNode::pushEventHandlerScope): Change to push handlers
+	on an existing scope chain rather than returning one. Name change too.
+        * khtml/ecma/kjs_dom.h: More of the same.
+        * khtml/ecma/kjs_html.cpp: (KJS::HTMLElement::pushEventHandlerScope): And here.
+        * khtml/ecma/kjs_html.h: And here.
+
+        * khtml/ecma/kjs_events.cpp: (JSEventListener::handleEvent): Use the pushEventHandlerScope
+	function, and also don't worry about optimizing the "no change" case, because that already
+	works pretty efficiently.
+
 2002-11-22  David Hyatt  <hyatt at apple.com>
 
 	Fix for the weather.com, slate and espn malformations that
diff --git a/WebCore/force-js-clean-timestamp b/WebCore/force-js-clean-timestamp
index f188739..6efee9f 100644
--- a/WebCore/force-js-clean-timestamp
+++ b/WebCore/force-js-clean-timestamp
@@ -1 +1 @@
-List -> ScopeChain 11/21 - Darin
+ScopeChain API 11/21 - Darin
diff --git a/WebCore/khtml/ecma/kjs_dom.cpp b/WebCore/khtml/ecma/kjs_dom.cpp
index 5b41a31..c69ca1d 100644
--- a/WebCore/khtml/ecma/kjs_dom.cpp
+++ b/WebCore/khtml/ecma/kjs_dom.cpp
@@ -415,9 +415,8 @@ Value DOMNode::getListener(int eventId) const
 	return Null();
 }
 
-ScopeChain DOMNode::eventHandlerScope(ExecState *) const
+void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
 {
-  return ScopeChain();
 }
 
 Value DOMNodeProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
diff --git a/WebCore/khtml/ecma/kjs_dom.h b/WebCore/khtml/ecma/kjs_dom.h
index 67bd378..3084c59 100644
--- a/WebCore/khtml/ecma/kjs_dom.h
+++ b/WebCore/khtml/ecma/kjs_dom.h
@@ -51,7 +51,7 @@ namespace KJS {
     virtual UString toString(ExecState *exec) const;
     void setListener(ExecState *exec, int eventId, Value func) const;
     Value getListener(int eventId) const;
-    virtual ScopeChain eventHandlerScope(ExecState *exec) const;
+    virtual void pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const;
 
     enum { NodeName, NodeValue, NodeType, ParentNode, ParentElement,
            ChildNodes, FirstChild, LastChild, PreviousSibling, NextSibling,
diff --git a/WebCore/khtml/ecma/kjs_events.cpp b/WebCore/khtml/ecma/kjs_events.cpp
index f9c5cc8..92454b8 100644
--- a/WebCore/khtml/ecma/kjs_events.cpp
+++ b/WebCore/khtml/ecma/kjs_events.cpp
@@ -72,16 +72,12 @@ void JSEventListener::handleEvent(DOM::Event &evt)
     // Add the event's target element to the scope
     // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope)
     Object thisObj = Object::dynamicCast(getDOMNode(exec,evt.currentTarget()));
-    ScopeChain scope;
     ScopeChain oldScope = listener.scope();
     //if (thisVal.type() != NullType)
     if ( !thisObj.isNull() ) {
-      scope = static_cast<DOMNode*>(thisObj.imp())->eventHandlerScope(exec);
-      if ( !scope.isEmpty() ) {
-        ScopeChain curScope = oldScope.copy();
-        curScope.prependList( scope );
-        listener.setScope( curScope );
-      }
+      ScopeChain scope = oldScope;
+      static_cast<DOMNode*>(thisObj.imp())->pushEventHandlerScope(exec, scope);
+      listener.setScope( scope );
     }
 
     Window *window = static_cast<Window*>(win.imp());
@@ -92,9 +88,7 @@ void JSEventListener::handleEvent(DOM::Event &evt)
 
     Value retval = listener.call(exec, thisObj, args);
 
-    if ( !scope.isEmpty() ) {
-      listener.setScope( oldScope );
-    }
+    listener.setScope( oldScope );
 
     window->setCurrentEvent( 0 );
     interpreter->setCurrentEvent( 0 );
diff --git a/WebCore/khtml/ecma/kjs_html.cpp b/WebCore/khtml/ecma/kjs_html.cpp
index dd95a3d..95594cd 100644
--- a/WebCore/khtml/ecma/kjs_html.cpp
+++ b/WebCore/khtml/ecma/kjs_html.cpp
@@ -1739,23 +1739,22 @@ UString KJS::HTMLElement::toString(ExecState *exec) const
     return DOMElement::toString(exec);
 }
 
-ScopeChain KJS::HTMLElement::eventHandlerScope(ExecState *exec) const
+void KJS::HTMLElement::pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const
 {
   DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
 
-  ScopeChain scope;
-  // The element is the first one, so that it is the most prioritary
-  scope.append(getDOMNode(exec,element));
+  // The document is put on first, fall back to searching it only after the element and form.
+  scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element.ownerDocument()).imp()));
 
+  // The form is next, searched before the document, but after the element itself.
   DOM::Node form = element.parentNode();
   while (!form.isNull() && form.elementId() != ID_FORM)
     form = form.parentNode();
   if (!form.isNull())
-    scope.append(getDOMNode(exec,form));
+    scope.push(static_cast<ObjectImp *>(getDOMNode(exec, form).imp()));
 
-  // The document is the last one, so that it is the least prioritary
-  scope.append(getDOMNode(exec,element.ownerDocument()));
-  return scope;
+  // The element is on top, searched first.
+  scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element).imp()));
 }
 
 HTMLElementFunction::HTMLElementFunction(ExecState *exec, int i, int len)
diff --git a/WebCore/khtml/ecma/kjs_html.h b/WebCore/khtml/ecma/kjs_html.h
index 8d2affd..b43d8cd 100644
--- a/WebCore/khtml/ecma/kjs_html.h
+++ b/WebCore/khtml/ecma/kjs_html.h
@@ -61,7 +61,7 @@ namespace KJS {
     void putValue(ExecState *exec, int token, const Value& value, int);
     virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
     virtual UString toString(ExecState *exec) const;
-    virtual ScopeChain eventHandlerScope(ExecState *exec) const;
+    virtual void pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const;
     virtual const ClassInfo* classInfo() const;
     static const ClassInfo info;
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list