- Fixed <rdar://problem/
4364705> run-javascriptcore-tests crashes in
KJS::BlockNode::deref
AKA
http://bugzilla.opendarwin.org/show_bug.cgi?id=6233
Reproducible stack-overflow crash in ~RefPtr<T> due to RefPtr<T> use in
linked lists
This patch does four things:
(1) Standardizes all our linked list nodes to use "next" as their next
pointers.
(2) Creates the ListRefPtr<T> class, a subclass of RefPtr<T> specialized
to iteratively deref "next" pointers.
(3) Standardizes our linked list nodes to use ListRefPtr<T> and
implement the releaseNext() function used by ~ListRefPtr<T>().
(4) Adds to RefPtr<T> the release() method used by releaseNext().
- Modified existing mozilla test to ensure it would make deployment
builds crash as well.
* JavaScriptCore.xcodeproj/project.pbxproj:
* kjs/nodes.cpp:
(ElementNode::evaluate):
(PropertyListNode::evaluate):
(ArgumentListNode::evaluateList):
(StatListNode::StatListNode):
(StatListNode::execute):
(StatListNode::processVarDecls):
(VarDeclListNode::evaluate):
(VarDeclListNode::processVarDecls):
(VarStatementNode::execute):
(VarStatementNode::processVarDecls):
(BlockNode::BlockNode):
(CaseClauseNode::evalStatements):
(CaseClauseNode::processVarDecls):
(ClauseListNode::processVarDecls):
(CaseBlockNode::CaseBlockNode):
(CaseBlockNode::evalBlock):
(SourceElementsNode::SourceElementsNode):
(SourceElementsNode::execute):
(SourceElementsNode::processFuncDecl):
(SourceElementsNode::processVarDecls):
* kjs/nodes.h:
(KJS::ElementNode::ElementNode):
(KJS::ElementNode::releaseNext):
(KJS::ArrayNode::ArrayNode):
(KJS::PropertyListNode::PropertyListNode):
(KJS::PropertyListNode::releaseNext):
(KJS::ObjectLiteralNode::ObjectLiteralNode):
(KJS::ArgumentListNode::ArgumentListNode):
(KJS::ArgumentListNode::releaseNext):
(KJS::ArgumentsNode::ArgumentsNode):
(KJS::StatListNode::releaseNext):
(KJS::VarDeclListNode::VarDeclListNode):
(KJS::VarDeclListNode::releaseNext):
(KJS::VarStatementNode::VarStatementNode):
(KJS::ForNode::ForNode):
(KJS::CaseClauseNode::CaseClauseNode):
(KJS::ClauseListNode::ClauseListNode):
(KJS::ClauseListNode::getClause):
(KJS::ClauseListNode::getNext):
(KJS::ClauseListNode::releaseNext):
(KJS::ParameterNode::ParameterNode):
(KJS::ParameterNode::releaseNext):
(KJS::SourceElementsNode::releaseNext):
* kjs/nodes2string.cpp:
(ElementNode::streamTo):
(PropertyListNode::streamTo):
(ArgumentListNode::streamTo):
(StatListNode::streamTo):
(VarDeclListNode::streamTo):
(VarStatementNode::streamTo):
(CaseClauseNode::streamTo):
(ClauseListNode::streamTo):
(CaseBlockNode::streamTo):
(SourceElementsNode::streamTo):
* kxmlcore/ListRefPtr.h: Added.
(KXMLCore::ListRefPtr::ListRefPtr):
(KXMLCore::ListRefPtr::~ListRefPtr):
(KXMLCore::ListRefPtr::operator=):
* kxmlcore/RefPtr.h:
(KXMLCore::RefPtr::release):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@11802
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2005-12-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by mjs.
+
+ - Fixed <rdar://problem/4364705> run-javascriptcore-tests crashes in
+ KJS::BlockNode::deref
+ AKA
+ http://bugzilla.opendarwin.org/show_bug.cgi?id=6233
+ Reproducible stack-overflow crash in ~RefPtr<T> due to RefPtr<T> use in
+ linked lists
+
+ This patch does four things:
+ (1) Standardizes all our linked list nodes to use "next" as their next
+ pointers.
+ (2) Creates the ListRefPtr<T> class, a subclass of RefPtr<T> specialized
+ to iteratively deref "next" pointers.
+ (3) Standardizes our linked list nodes to use ListRefPtr<T> and
+ implement the releaseNext() function used by ~ListRefPtr<T>().
+ (4) Adds to RefPtr<T> the release() method used by releaseNext().
+
+ - Modified existing mozilla test to ensure it would make deployment
+ builds crash as well.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/nodes.cpp:
+ (ElementNode::evaluate):
+ (PropertyListNode::evaluate):
+ (ArgumentListNode::evaluateList):
+ (StatListNode::StatListNode):
+ (StatListNode::execute):
+ (StatListNode::processVarDecls):
+ (VarDeclListNode::evaluate):
+ (VarDeclListNode::processVarDecls):
+ (VarStatementNode::execute):
+ (VarStatementNode::processVarDecls):
+ (BlockNode::BlockNode):
+ (CaseClauseNode::evalStatements):
+ (CaseClauseNode::processVarDecls):
+ (ClauseListNode::processVarDecls):
+ (CaseBlockNode::CaseBlockNode):
+ (CaseBlockNode::evalBlock):
+ (SourceElementsNode::SourceElementsNode):
+ (SourceElementsNode::execute):
+ (SourceElementsNode::processFuncDecl):
+ (SourceElementsNode::processVarDecls):
+ * kjs/nodes.h:
+ (KJS::ElementNode::ElementNode):
+ (KJS::ElementNode::releaseNext):
+ (KJS::ArrayNode::ArrayNode):
+ (KJS::PropertyListNode::PropertyListNode):
+ (KJS::PropertyListNode::releaseNext):
+ (KJS::ObjectLiteralNode::ObjectLiteralNode):
+ (KJS::ArgumentListNode::ArgumentListNode):
+ (KJS::ArgumentListNode::releaseNext):
+ (KJS::ArgumentsNode::ArgumentsNode):
+ (KJS::StatListNode::releaseNext):
+ (KJS::VarDeclListNode::VarDeclListNode):
+ (KJS::VarDeclListNode::releaseNext):
+ (KJS::VarStatementNode::VarStatementNode):
+ (KJS::ForNode::ForNode):
+ (KJS::CaseClauseNode::CaseClauseNode):
+ (KJS::ClauseListNode::ClauseListNode):
+ (KJS::ClauseListNode::getClause):
+ (KJS::ClauseListNode::getNext):
+ (KJS::ClauseListNode::releaseNext):
+ (KJS::ParameterNode::ParameterNode):
+ (KJS::ParameterNode::releaseNext):
+ (KJS::SourceElementsNode::releaseNext):
+ * kjs/nodes2string.cpp:
+ (ElementNode::streamTo):
+ (PropertyListNode::streamTo):
+ (ArgumentListNode::streamTo):
+ (StatListNode::streamTo):
+ (VarDeclListNode::streamTo):
+ (VarStatementNode::streamTo):
+ (CaseClauseNode::streamTo):
+ (ClauseListNode::streamTo):
+ (CaseBlockNode::streamTo):
+ (SourceElementsNode::streamTo):
+ * kxmlcore/ListRefPtr.h: Added.
+ (KXMLCore::ListRefPtr::ListRefPtr):
+ (KXMLCore::ListRefPtr::~ListRefPtr):
+ (KXMLCore::ListRefPtr::operator=):
+ * kxmlcore/RefPtr.h:
+ (KXMLCore::RefPtr::release):
+
2005-12-29 Geoffrey Garen <ggaren@apple.com>
Reviewed by mjs.
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1626095D16BB00666D0D /* ListRefPtr.h */; };
652C107F08DA7B1E0020887D /* protected_reference.h in Headers */ = {isa = PBXBuildFile; fileRef = 652C107E08DA7B1E0020887D /* protected_reference.h */; };
6541BD7208E80A17002CBEE7 /* TCPageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */; };
6541BD7308E80A17002CBEE7 /* TCSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */; };
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
+ 148A1626095D16BB00666D0D /* ListRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListRefPtr.h; sourceTree = "<group>"; };
45E12D8806A49B0F00E9DF84 /* testkjs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = testkjs.cpp; sourceTree = "<group>"; tabWidth = 8; };
5114F47B05E4426200D1BBBD /* runtime_root.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = runtime_root.cpp; path = bindings/runtime_root.cpp; sourceTree = "<group>"; tabWidth = 8; };
5114F47C05E4426200D1BBBD /* runtime_root.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = runtime_root.h; path = bindings/runtime_root.h; sourceTree = "<group>"; tabWidth = 8; };
657EEBBF094E445E008C9C7B /* HashCountedSet.h */,
65C647B3093EF8D60022C380 /* RefPtr.h */,
6580F795094070560082C219 /* PassRefPtr.h */,
+ 148A1626095D16BB00666D0D /* ListRefPtr.h */,
65D7D19B08F10B5B0015ABD8 /* FastMallocInternal.h */,
6557E8F708EA5D4D0049CDFC /* HashMapPtrSpec.h */,
65DFC92A08EA173A00F7300B /* HashFunctions.h */,
6580F796094070560082C219 /* PassRefPtr.h in Headers */,
657EEBC0094E445E008C9C7B /* HashCountedSet.h in Headers */,
93AA4F780957251F0084B3A7 /* AlwaysInline.h in Headers */,
+ 148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
{
JSObject *array = exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty());
int length = 0;
- for (ElementNode *n = this; n; n = n->list.get()) {
+ for (ElementNode *n = this; n; n = n->next.get()) {
JSValue *val = n->node->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
length += n->elision;
{
JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
- for (PropertyListNode *p = this; p; p = p->list.get()) {
+ for (PropertyListNode *p = this; p; p = p->next.get()) {
JSValue *n = p->node->name->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
JSValue *v = p->node->assign->evaluate(exec);
{
List l;
- for (ArgumentListNode *n = this; n; n = n->list.get()) {
+ for (ArgumentListNode *n = this; n; n = n->next.get()) {
JSValue *v = n->expr->evaluate(exec);
KJS_CHECKEXCEPTIONLIST
l.append(v);
// ------------------------------ StatListNode ---------------------------------
StatListNode::StatListNode(StatementNode *s)
- : statement(s), list(this)
+ : statement(s), next(this)
{
setLoc(s->firstLine(), s->lastLine(), s->sourceId());
}
StatListNode::StatListNode(StatListNode *l, StatementNode *s)
- : statement(s), list(l->list)
+ : statement(s), next(l->next)
{
- l->list = this;
+ l->next = this;
setLoc(l->firstLine(), s->lastLine(), l->sourceId());
}
JSValue *v = c.value();
- for (StatListNode *n = list.get(); n; n = n->list.get()) {
+ for (StatListNode *n = next.get(); n; n = n->next.get()) {
Completion c2 = n->statement->execute(exec);
KJS_ABORTPOINT
if (c2.complType() != Normal)
void StatListNode::processVarDecls(ExecState *exec)
{
- for (StatListNode *n = this; n; n = n->list.get())
+ for (StatListNode *n = this; n; n = n->next.get())
n->statement->processVarDecls(exec);
}
// ECMA 12.2
JSValue *VarDeclListNode::evaluate(ExecState *exec)
{
- for (VarDeclListNode *n = this; n; n = n->list.get()) {
+ for (VarDeclListNode *n = this; n; n = n->next.get()) {
n->var->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
}
void VarDeclListNode::processVarDecls(ExecState *exec)
{
- for (VarDeclListNode *n = this; n; n = n->list.get())
+ for (VarDeclListNode *n = this; n; n = n->next.get())
n->var->processVarDecls(exec);
}
{
KJS_BREAKPOINT;
- (void) list->evaluate(exec);
+ (void) next->evaluate(exec);
KJS_CHECKEXCEPTION
return Completion(Normal);
void VarStatementNode::processVarDecls(ExecState *exec)
{
- list->processVarDecls(exec);
+ next->processVarDecls(exec);
}
// ------------------------------ BlockNode ------------------------------------
BlockNode::BlockNode(SourceElementsNode *s)
{
if (s) {
- source = s->elements;
- s->elements = 0;
+ source = s->next;
+ s->next = 0;
setLoc(s->firstLine(), s->lastLine(), s->sourceId());
} else {
source = 0;
// ECMA 12.11
Completion CaseClauseNode::evalStatements(ExecState *exec)
{
- if (list)
- return list->execute(exec);
+ if (next)
+ return next->execute(exec);
else
return Completion(Normal, jsUndefined());
}
void CaseClauseNode::processVarDecls(ExecState *exec)
{
- if (list)
- list->processVarDecls(exec);
+ if (next)
+ next->processVarDecls(exec);
}
// ------------------------------ ClauseListNode -------------------------------
// ECMA 12.11
void ClauseListNode::processVarDecls(ExecState *exec)
{
- for (ClauseListNode *n = this; n; n = n->nx.get())
- if (n->cl)
- n->cl->processVarDecls(exec);
+ for (ClauseListNode *n = this; n; n = n->next.get())
+ if (n->clause)
+ n->clause->processVarDecls(exec);
}
// ------------------------------ CaseBlockNode --------------------------------
ClauseListNode *l2)
{
if (l1) {
- list1 = l1->nx;
- l1->nx = 0;
+ list1 = l1->next;
+ l1->next = 0;
} else {
list1 = 0;
}
def = d;
if (l2) {
- list2 = l2->nx;
- l2->nx = 0;
+ list2 = l2->next;
+ l2->next = 0;
} else {
list2 = 0;
}
CaseClauseNode *clause;
while (a) {
- clause = a->clause();
- a = a->next();
+ clause = a->getClause();
+ a = a->getNext();
v = clause->evaluate(exec);
KJS_CHECKEXCEPTION
if (strictEqual(exec, input, v)) {
if (res.complType() != Normal)
return res;
while (a) {
- res = a->clause()->evalStatements(exec);
+ res = a->getClause()->evalStatements(exec);
if (res.complType() != Normal)
return res;
- a = a->next();
+ a = a->getNext();
}
break;
}
}
while (b) {
- clause = b->clause();
- b = b->next();
+ clause = b->getClause();
+ b = b->getNext();
v = clause->evaluate(exec);
KJS_CHECKEXCEPTION
if (strictEqual(exec, input, v)) {
b = list2.get();
step18:
while (b) {
- clause = b->clause();
+ clause = b->getClause();
res = clause->evalStatements(exec);
if (res.complType() != Normal)
return res;
- b = b->next();
+ b = b->getNext();
}
// bail out on error
// ------------------------------ SourceElementsNode ---------------------------
+int SourceElementsNode::count = 0;
+
SourceElementsNode::SourceElementsNode(StatementNode *s1)
- : element(s1), elements(this)
+ : node(s1), next(this)
{
setLoc(s1->firstLine(), s1->lastLine(), s1->sourceId());
}
-
+
SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
- : element(s2), elements(s1->elements)
+ : node(s2), next(s1->next)
{
- s1->elements = this;
+ s1->next = this;
setLoc(s1->firstLine(), s2->lastLine(), s1->sourceId());
}
{
KJS_CHECKEXCEPTION
- Completion c1 = element->execute(exec);
+ Completion c1 = node->execute(exec);
KJS_CHECKEXCEPTION;
if (c1.complType() != Normal)
return c1;
- for (SourceElementsNode *n = elements.get(); n; n = n->elements.get()) {
- Completion c2 = n->element->execute(exec);
+ for (SourceElementsNode *n = next.get(); n; n = n->next.get()) {
+ Completion c2 = n->node->execute(exec);
if (c2.complType() != Normal)
return c2;
// The spec says to return c2 here, but it seems that mozilla returns c1 if
// ECMA 14
void SourceElementsNode::processFuncDecl(ExecState *exec)
{
- for (SourceElementsNode *n = this; n; n = n->elements.get())
- n->element->processFuncDecl(exec);
+ for (SourceElementsNode *n = this; n; n = n->next.get())
+ n->node->processFuncDecl(exec);
}
void SourceElementsNode::processVarDecls(ExecState *exec)
{
- for (SourceElementsNode *n = this; n; n = n->elements.get())
- n->element->processVarDecls(exec);
+ for (SourceElementsNode *n = this; n; n = n->next.get())
+ n->node->processVarDecls(exec);
}
ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
#define _NODES_H_
#include <kxmlcore/RefPtr.h>
+#include <kxmlcore/ListRefPtr.h>
#include "internal.h"
class ElementNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ArrayNode ctor
- ElementNode(int e, Node *n) : list(this), elision(e), node(n) { }
+ ElementNode(int e, Node *n) : next(this), elision(e), node(n) { }
ElementNode(ElementNode *l, int e, Node *n)
- : list(l->list), elision(e), node(n) { l->list = this; }
+ : next(l->next), elision(e), node(n) { l->next = this; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<ElementNode> releaseNext() { return next.release(); }
private:
friend class ArrayNode;
- RefPtr<ElementNode> list;
+ ListRefPtr<ElementNode> next;
int elision;
RefPtr<Node> node;
};
public:
ArrayNode(int e) : element(0), elision(e), opt(true) { }
ArrayNode(ElementNode *ele)
- : element(ele->list), elision(0), opt(false) { ele->list = 0; }
+ : element(ele->next), elision(0), opt(false) { ele->next = 0; }
ArrayNode(int eli, ElementNode *ele)
- : element(ele->list), elision(eli), opt(true) { ele->list = 0; }
+ : element(ele->next), elision(eli), opt(true) { ele->next = 0; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
class PropertyListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ObjectLiteralNode ctor
- PropertyListNode(PropertyNode *n)\v
- : node(n), list(this) { }
+ PropertyListNode(PropertyNode *n)
+ : node(n), next(this) { }
PropertyListNode(PropertyNode *n, PropertyListNode *l)
- : node(n), list(l->list) { l->list = this; }
+ : node(n), next(l->next) { l->next = this; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<PropertyListNode> releaseNext() { return next.release(); }
private:
friend class ObjectLiteralNode;
RefPtr<PropertyNode> node;
- RefPtr<PropertyListNode> list;
+ ListRefPtr<PropertyListNode> next;
};
class ObjectLiteralNode : public Node {
public:
ObjectLiteralNode() : list(0) { }
- ObjectLiteralNode(PropertyListNode *l) : list(l->list) { l->list = 0; }
+ ObjectLiteralNode(PropertyListNode *l) : list(l->next) { l->next = 0; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
class ArgumentListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ArgumentsNode ctor
- ArgumentListNode(Node *e) : list(this), expr(e) { }
+ ArgumentListNode(Node *e) : next(this), expr(e) { }
ArgumentListNode(ArgumentListNode *l, Node *e)
- : list(l->list), expr(e) { l->list = this; }
+ : next(l->next), expr(e) { l->next = this; }
JSValue *evaluate(ExecState *exec);
List evaluateList(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<ArgumentListNode> releaseNext() { return next.release(); }
private:
friend class ArgumentsNode;
- RefPtr<ArgumentListNode> list;
+ ListRefPtr<ArgumentListNode> next;
RefPtr<Node> expr;
};
public:
ArgumentsNode() : list(0) { }
ArgumentsNode(ArgumentListNode *l)
- : list(l->list) { l->list = 0; }
+ : list(l->next) { l->next = 0; }
JSValue *evaluate(ExecState *exec);
List evaluateList(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
virtual Completion execute(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<StatListNode> releaseNext() { return next.release(); }
private:
friend class CaseClauseNode;
RefPtr<StatementNode> statement;
- RefPtr<StatListNode> list;
+ ListRefPtr<StatListNode> next;
};
class AssignExprNode : public Node {
class VarDeclListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ForNode/VarStatementNode ctor
- VarDeclListNode(VarDeclNode *v) : list(this), var(v) {}
+ VarDeclListNode(VarDeclNode *v) : next(this), var(v) {}
VarDeclListNode(VarDeclListNode *l, VarDeclNode *v)
- : list(l->list), var(v) { l->list = this; }
+ : next(l->next), var(v) { l->next = this; }
JSValue *evaluate(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<VarDeclListNode> releaseNext() { return next.release(); }
private:
friend class ForNode;
friend class VarStatementNode;
- RefPtr<VarDeclListNode> list;
+ ListRefPtr<VarDeclListNode> next;
RefPtr<VarDeclNode> var;
};
class VarStatementNode : public StatementNode {
public:
- VarStatementNode(VarDeclListNode *l) : list(l->list) { l->list = 0; }
+ VarStatementNode(VarDeclListNode *l) : next(l->next) { l->next = 0; }
virtual Completion execute(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
- RefPtr<VarDeclListNode> list;
+ RefPtr<VarDeclListNode> next;
};
class BlockNode : public StatementNode {
ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) :
expr1(e1), expr2(e2), expr3(e3), statement(s) {}
ForNode(VarDeclListNode *e1, Node *e2, Node *e3, StatementNode *s) :
- expr1(e1->list), expr2(e2), expr3(e3), statement(s) { e1->list = 0; }
+ expr1(e1->next), expr2(e2), expr3(e3), statement(s) { e1->next = 0; }
virtual Completion execute(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
class CaseClauseNode : public Node {
public:
- CaseClauseNode(Node *e) : expr(e), list(0) { }
+ CaseClauseNode(Node *e) : expr(e), next(0) { }
CaseClauseNode(Node *e, StatListNode *l)
- : expr(e), list(l->list) { l->list = 0; }
+ : expr(e), next(l->next) { l->next = 0; }
JSValue *evaluate(ExecState *exec);
Completion evalStatements(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
RefPtr<Node> expr;
- RefPtr<StatListNode> list;
+ RefPtr<StatListNode> next;
};
class ClauseListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the CaseBlockNode ctor
- ClauseListNode(CaseClauseNode *c) : cl(c), nx(this) { }
+ ClauseListNode(CaseClauseNode *c) : clause(c), next(this) { }
ClauseListNode(ClauseListNode *n, CaseClauseNode *c)
- : cl(c), nx(n->nx) { n->nx = this; }
+ : clause(c), next(n->next) { n->next = this; }
JSValue *evaluate(ExecState *exec);
- CaseClauseNode *clause() const { return cl.get(); }
- ClauseListNode *next() const { return nx.get(); }
+ CaseClauseNode *getClause() const { return clause.get(); }
+ ClauseListNode *getNext() const { return next.get(); }
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<ClauseListNode> releaseNext() { return next.release(); }
private:
friend class CaseBlockNode;
- RefPtr<CaseClauseNode> cl;
- RefPtr<ClauseListNode> nx;
+ RefPtr<CaseClauseNode> clause;
+ ListRefPtr<ClauseListNode> next;
};
class CaseBlockNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the FuncDeclNode/FuncExprNode ctor
ParameterNode(const Identifier &i) : id(i), next(this) { }
- ParameterNode(ParameterNode *list, const Identifier &i)
- : id(i), next(list->next) { list->next = this; }
+ ParameterNode(ParameterNode *next, const Identifier &i)
+ : id(i), next(next->next) { next->next = this; }
JSValue *evaluate(ExecState *exec);
Identifier ident() { return id; }
ParameterNode *nextParam() { return next.get(); }
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<ParameterNode> releaseNext() { return next.release(); }
private:
friend class FuncDeclNode;
friend class FuncExprNode;
Identifier id;
- RefPtr<ParameterNode> next;
+ ListRefPtr<ParameterNode> next;
};
// inherited by ProgramNode
// A linked list of source element nodes
class SourceElementsNode : public StatementNode {
public:
+ static int count;
// list pointer is tail of a circular list, cracked in the BlockNode (or subclass) ctor
SourceElementsNode(StatementNode *s1);
SourceElementsNode(SourceElementsNode *s1, StatementNode *s2);
-
+
Completion execute(ExecState *exec);
void processFuncDecl(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
+ PassRefPtr<SourceElementsNode> releaseNext() { return next.release(); }
private:
friend class BlockNode;
- RefPtr<StatementNode> element; // 'this' element
- RefPtr<SourceElementsNode> elements; // pointer to next
+ RefPtr<StatementNode> node;
+ ListRefPtr<SourceElementsNode> next;
};
class ProgramNode : public FunctionBodyNode {
void ElementNode::streamTo(SourceStream &s) const
{
- for (const ElementNode *n = this; n; n = n->list.get()) {
+ for (const ElementNode *n = this; n; n = n->next.get()) {
for (int i = 0; i < n->elision; i++)
s << ",";
s << n->node;
{
s << node;
- for (const PropertyListNode *n = list.get(); n; n = n->list.get())
+ for (const PropertyListNode *n = next.get(); n; n = n->next.get())
s << ", " << n->node;
}
void ArgumentListNode::streamTo(SourceStream &s) const
{
s << expr;
- for (ArgumentListNode *n = list.get(); n; n = n->list.get())
+ for (ArgumentListNode *n = next.get(); n; n = n->next.get())
s << ", " << n->expr;
}
void StatListNode::streamTo(SourceStream &s) const
{
- for (const StatListNode *n = this; n; n = n->list.get())
+ for (const StatListNode *n = this; n; n = n->next.get())
s << n->statement;
}
void VarDeclListNode::streamTo(SourceStream &s) const
{
s << var;
- for (VarDeclListNode *n = list.get(); n; n = n->list.get())
+ for (VarDeclListNode *n = next.get(); n; n = n->next.get())
s << ", " << n->var;
}
void VarStatementNode::streamTo(SourceStream &s) const
{
- s << SourceStream::Endl << "var " << list << ";";
+ s << SourceStream::Endl << "var " << next << ";";
}
void BlockNode::streamTo(SourceStream &s) const
else
s << "default";
s << ":" << SourceStream::Indent;
- if (list)
- s << list;
+ if (next)
+ s << next;
s << SourceStream::Unindent;
}
void ClauseListNode::streamTo(SourceStream &s) const
{
- for (const ClauseListNode *n = this; n; n = n->next())
- s << n->clause();
+ for (const ClauseListNode *n = this; n; n = n->getNext())
+ s << n->getClause();
}
void CaseBlockNode::streamTo(SourceStream &s) const
{
- for (const ClauseListNode *n = list1.get(); n; n = n->next())
- s << n->clause();
+ for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
+ s << n->getClause();
if (def)
s << def;
- for (const ClauseListNode *n = list2.get(); n; n = n->next())
- s << n->clause();
+ for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
+ s << n->getClause();
}
void SwitchNode::streamTo(SourceStream &s) const
void SourceElementsNode::streamTo(SourceStream &s) const
{
- for (const SourceElementsNode *n = this; n; n = n->elements.get())
- s << n->element;
+ for (const SourceElementsNode *n = this; n; n = n->next.get())
+ s << n->node;
}
--- /dev/null
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2005 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
+ * 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 Steet, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KXMLCORE_LIST_REF_PTR_H
+#define KXMLCORE_LIST_REF_PTR_H
+
+#include <kxmlcore/RefPtr.h>
+#include <algorithm>
+
+namespace KXMLCore {
+
+ // Specialized version of RefPtr desgined for use in singly-linked lists.
+ // Derefs the list iteratively to avoid recursive derefing that can overflow the stack.
+ template <typename T> class ListRefPtr : public RefPtr<T>
+ {
+ public:
+ ListRefPtr() : RefPtr<T>() {}
+ ListRefPtr(T *ptr) : RefPtr<T>(ptr) {}
+ ListRefPtr(const RefPtr<T>& o) : RefPtr<T>(o) {}
+ // see comment in PassRefPtr.h for why this takes const reference
+ template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {}
+
+ ~ListRefPtr() {
+ RefPtr<T> reaper = this->release();
+ while (reaper && reaper->refcount() == 1)
+ reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper
+ }
+
+ ListRefPtr& operator=(T *optr) { RefPtr<T>::operator=(optr); return *this; }
+ ListRefPtr& operator=(const RefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; }
+ ListRefPtr& operator=(const PassRefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; }
+ template <typename U> ListRefPtr& operator=(const RefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; }
+ template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; }
+ };
+
+} // namespace KXMLCore
+
+using KXMLCore::ListRefPtr;
+
+#endif // KXMLCORE_LIST_REF_PTR_H
T *get() const { return m_ptr; }
+ PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
+
T& operator*() const { return *m_ptr; }
T *operator->() const { return m_ptr; }
* SUMMARY: Testing script with at least 64K of different string literals
* See http://bugzilla.mozilla.org/show_bug.cgi?id=159334
*
-* Testing that script engine can handle scripts with at least 64K of different
+* Testing that script engine can handle scripts with at least 128K of different
* string literals. The following will evaluate, via eval(), a script like this:
*
* f('0')
* ...
* f('N - 1')
*
-* where N is 0xFFFE
+* where N is 0x20000
*
*/
//-----------------------------------------------------------------------------
var UBound = 0;
var bug = 159334;
-var summary = 'Testing script with at least 64K of different string literals';
+var summary = 'Testing script with at least 128K of different string literals';
var status = '';
var statusitems = [];
var actual = '';
var expectedvalues = [];
-var N = 0xFFFE;
+var N = 0x20000;
// Create big string for eval recursively to avoid N*N behavior
// on string concatenation