Changeset 47571 in webkit for trunk/JavaScriptCore/parser


Ignore:
Timestamp:
Aug 20, 2009, 7:24:49 AM (16 years ago)
Author:
Darin Adler
Message:

Syntax tree nodes should use arena allocation
https://bugs.webkit.org/show_bug.cgi?id=25674

Patch by Darin Adler <Darin Adler> on 2009-08-20
Reviewed by Gavin Barraclough.

Use an actual arena now. 0.7% speedup on SunSpider.

longer needs to be used outside JavaScriptCore.

Executable.h project-internal instead of "private".

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator): Updated since VarStack
contains const Identifier* now.

  • parser/Grammar.y: Made identifiers from the lexer be const

Identifier* and updated since VarStack contains const Identifier* now.

  • parser/Lexer.cpp:

(JSC::Lexer::setCode): Pass in ParserArena, used for identifiers.
(JSC::Lexer::makeIdentifier): Changed return type to const Identifier*
and changed to call ParserArena.
(JSC::Lexer::clear): Removed the code to manage m_identifiers and
added code to set m_arena to 0.

  • parser/Lexer.h: Updated for changes above.
  • parser/NodeConstructors.h:

(JSC::ParserArenaFreeable::operator new): Added. Calls allocateFreeable
on the arena.
(JSC::ParserArenaDeletable::operator new): Changed to call the
allocateDeletable function on the arena instead of deleteWithArena.
(JSC::PropertyNode::PropertyNode): Added new constructor that makes
numeric identifiers. Some day we might want to optimize this for
integers so it doesn't create a string for each one.
(JSC::ContinueNode::ContinueNode): Initialize m_ident to nullIdentifier
since it's now a const Identifier& so it can't be left uninitialized.
(JSC::BreakNode::BreakNode): Ditto.
(JSC::CaseClauseNode::CaseClauseNode): Updated to use SourceElements*
to keep track of the statements rather than a separate statement vector.
(JSC::BlockNode::BlockNode): Ditto.
(JSC::ForInNode::ForInNode): Initialize m_ident to nullIdentifier.

  • parser/Nodes.cpp: Moved the comment explaining emitBytecode in here.

It seemed strangely out of place in the header.
(JSC::ThrowableExpressionData::emitThrowError): Added an overload for
UString as well as Identifier.
(JSC::SourceElements::singleStatement): Added.
(JSC::SourceElements::lastStatement): Added.
(JSC::RegExpNode::emitBytecode): Changed the throwError code to use
the substitution mechanism instead of doing a string append.
(JSC::SourceElements::emitBytecode): Added. Replaces the old
statementListEmitCode function, since we now keep the SourceElements
objects around.
(JSC::BlockNode::lastStatement): Added.
(JSC::BlockNode::emitBytecode): Changed to use emitBytecode instead of
statementListEmitCode.
(JSC::CaseClauseNode::emitBytecode): Added.
(JSC::CaseBlockNode::emitBytecodeForBlock): Changed to use emitBytecode
instead of statementListEmitCode.
(JSC::ScopeNodeData::ScopeNodeData): Changed to store the
SourceElements* instead of using releaseContentsIntoVector.
(JSC::ScopeNode::emitStatementsBytecode): Added.
(JSC::ScopeNode::singleStatement): Added.
(JSC::ProgramNode::emitBytecode): Call emitStatementsBytecode instead
of statementListEmitCode.
(JSC::EvalNode::emitBytecode): Ditto.
(JSC::FunctionBodyNode::emitBytecode): Call emitStatementsBytecode
insetad of statementListEmitCode and check for the return node using
the new functions.

  • parser/Nodes.h: Changed VarStack to store const Identifier* instead

of Identifier and rely on the arena to control lifetime. Added a new
ParserArenaFreeable class. Made ParserArenaDeletable inherit from
FastAllocBase instead of having its own operator new. Base the Node
class on ParserArenaFreeable. Changed the various Node classes
to use const Identifier& instead of Identifier to avoid the need to
call their destructors and allow them to function as "freeable" in the
arena. Removed extraneous JSC_FAST_CALL on definitions of inline functions.
Changed ElementNode, PropertyNode, ArgumentsNode, ParameterNode,
CaseClauseNode, ClauseListNode, and CaseBlockNode to use ParserArenaFreeable
as a base class since they do not descend from Node. Eliminated the
StatementVector type and instead have various classes use SourceElements*
instead of StatementVector. This prevents those classes from having to
use ParserArenaDeletable to make sure the vector destructor is called.

  • parser/Parser.cpp:

(JSC::Parser::parse): Pass the arena to the lexer.

  • parser/Parser.h: Added an include of ParserArena.h, which is no longer

included by Nodes.h.
(JSC::Parser::parseFunctionFromGlobalCode): Changed to use the
singleStatement function, since there is no longer any children function.
Removed some unneeded use of RefPtr.

  • parser/ParserArena.cpp:

(JSC::ParserArena::ParserArena): Added. Initializes the new members,
m_freeableMemory, m_freeablePoolEnd, and m_identifiers.
(JSC::ParserArena::freeablePool): Added. Computes the pool pointer,
since we store only the current pointer and the end of pool pointer.
(JSC::ParserArena::deallocateObjects): Added. Contains the common
memory-deallocation logic used by both the destructor and the
reset function.
(JSC::ParserArena::~ParserArena): Changed to call deallocateObjects.
(JSC::ParserArena::reset): Ditto. Also added code to zero out the
new structures, and switched to use clear() instead of shrink(0) since
we don't really reuse arenas.
(JSC::ParserArena::makeNumericIdentifier): Added.
(JSC::ParserArena::allocateFreeablePool): Added. Used when the pool
is empty.
(JSC::ParserArena::isEmpty): Added. No longer inline, which is fine
since this is used only for assertions at the moment.

  • parser/ParserArena.h: Added an actual arena of "freeable" objects,

ones that don't need destructors to be called. Also added a separate
IdentifierArena object, a segmented vector of identifiers that used
to be in the Lexer.

  • runtime/Executable.h: Moved the definition of the

FunctionExecutable::make function here. It can't go in JSFunction.h
since that header has to be used outside JavaScriptCore and so can't
include this, which includes Nodes.h. The function could be moved
elswhere if we don't want to include JSFunction.h in this header, but
for now this seems to be the best place.

  • runtime/JSFunction.h: Removed the include of Executable.h and

definition of the FunctionExecutable::make function.

  • wtf/FastMalloc.cpp: Fixed an incorrect comment.
Location:
trunk/JavaScriptCore/parser
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/parser/Grammar.y

    r47264 r47571  
    126126}
    127127
    128 static void appendToVarDeclarationList(JSGlobalData* globalData, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
     128static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
    129129{
    130130    if (!varDecls)
    131131        varDecls = new (globalData) ParserArenaData<DeclarationStacks::VarStack>;
    132132
    133     varDecls->data.append(make_pair(ident, attrs));
    134 
     133    varDecls->data.append(make_pair(&ident, attrs));
    135134}
    136135
     
    148147    int                 intValue;
    149148    double              doubleValue;
    150     Identifier*         ident;
     149    const Identifier*   ident;
    151150
    152151    // expression subtrees
  • trunk/JavaScriptCore/parser/Lexer.cpp

    r47236 r47571  
    142142}
    143143
    144 void Lexer::setCode(const SourceCode& source)
    145 {
     144void Lexer::setCode(const SourceCode& source, ParserArena& arena)
     145{
     146    m_arena = &arena.identifierArena();
     147
    146148    m_lineNumber = source.firstLine();
    147149    m_delimited = false;
     
    205207}
    206208
    207 ALWAYS_INLINE Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
    208 {
    209     m_identifiers.append(Identifier(m_globalData, characters, length));
    210     return &m_identifiers.last();
     209ALWAYS_INLINE const Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
     210{
     211    return &m_arena->makeIdentifier(m_globalData, characters, length);
    211212}
    212213
     
    10121013void Lexer::clear()
    10131014{
    1014     m_identifiers.clear();
     1015    m_arena = 0;
    10151016    m_codeWithoutBOMs.clear();
    10161017
  • trunk/JavaScriptCore/parser/Lexer.h

    r47236 r47571  
    2424
    2525#include "Lookup.h"
     26#include "ParserArena.h"
    2627#include "SourceCode.h"
    2728#include <wtf/ASCIICType.h>
     
    4344
    4445        // Functions to set up parsing.
    45         void setCode(const SourceCode&);
     46        void setCode(const SourceCode&, ParserArena&);
    4647        void setIsReparsing() { m_isReparsing = true; }
    4748
     
    7980        const UChar* currentCharacter() const;
    8081
    81         JSC::Identifier* makeIdentifier(const UChar* buffer, size_t length);
     82        const Identifier* makeIdentifier(const UChar* characters, size_t length);
    8283
    8384        bool lastTokenWasRestrKeyword() const;
    8485
    8586        static const size_t initialReadBufferCapacity = 32;
    86         static const size_t initialIdentifierTableCapacity = 64;
    8787
    8888        int m_lineNumber;
     
    108108        int m_next3;
    109109       
    110         WTF::SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers;
     110        IdentifierArena* m_arena;
    111111
    112112        JSGlobalData* m_globalData;
  • trunk/JavaScriptCore/parser/NodeConstructors.h

    r47259 r47571  
    2828namespace JSC {
    2929
     30    inline void* ParserArenaFreeable::operator new(size_t size, JSGlobalData* globalData)
     31    {
     32        return globalData->parser->arena().allocateFreeable(size);
     33    }
     34
    3035    inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData)
    3136    {
    32         ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size));
    33         globalData->parser->arena().deleteWithArena(deletable);
    34         return deletable;
    35     }
    36 
    37     inline void* ParserArenaDeletable::operator new(size_t size)
    38     {
    39         return fastMalloc(size);
    40     }
    41 
    42     inline void ParserArenaDeletable::operator delete(void* p)
    43     {
    44         fastFree(p);
     37        return globalData->parser->arena().allocateDeletable(size);
    4538    }
    4639
     
    7871    }
    7972
    80     inline NumberNode::NumberNode(JSGlobalData* globalData, double v)
     73    inline NumberNode::NumberNode(JSGlobalData* globalData, double value)
    8174        : ExpressionNode(globalData, ResultType::numberType())
    82         , m_double(v)
    83     {
    84     }
    85 
    86     inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& v)
     75        , m_value(value)
     76    {
     77    }
     78
     79    inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& value)
    8780        : ExpressionNode(globalData, ResultType::stringType())
    88         , m_value(v)
     81        , m_value(value)
    8982    {
    9083    }
     
    156149
    157150    inline PropertyNode::PropertyNode(JSGlobalData* globalData, double name, ExpressionNode* assign, Type type)
    158         : m_name(Identifier(globalData, UString::from(name)))
     151        : m_name(globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name))
    159152        , m_assign(assign)
    160153        , m_type(type)
     
    749742    inline ContinueNode::ContinueNode(JSGlobalData* globalData)
    750743        : StatementNode(globalData)
     744        , m_ident(globalData->propertyNames->nullIdentifier)
    751745    {
    752746    }
     
    760754    inline BreakNode::BreakNode(JSGlobalData* globalData)
    761755        : StatementNode(globalData)
     756        , m_ident(globalData->propertyNames->nullIdentifier)
    762757    {
    763758    }
     
    834829    }
    835830
    836     inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr)
     831    inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* statements)
    837832        : m_expr(expr)
    838     {
    839     }
    840 
    841     inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* children)
    842         : m_expr(expr)
    843     {
    844         if (children)
    845             children->releaseContentsIntoVector(m_children);
     833        , m_statements(statements)
     834    {
    846835    }
    847836
     
    881870    }
    882871
    883     inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
    884         : StatementNode(globalData)
    885     {
    886         if (children)
    887             children->releaseContentsIntoVector(m_children);
     872    inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* statements)
     873        : StatementNode(globalData)
     874        , m_statements(statements)
     875    {
    888876    }
    889877
    890878    inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
    891879        : StatementNode(globalData)
     880        , m_ident(globalData->propertyNames->nullIdentifier)
    892881        , m_init(0)
    893882        , m_lexpr(l)
  • trunk/JavaScriptCore/parser/Nodes.cpp

    r47412 r47571  
    5050namespace JSC {
    5151
    52 static void substitute(UString& string, const UString& substring);
     52/*
     53    Details of the emitBytecode function.
     54
     55    Return value: The register holding the production's value.
     56             dst: An optional parameter specifying the most efficient destination at
     57                  which to store the production's value. The callee must honor dst.
     58
     59    The dst argument provides for a crude form of copy propagation. For example,
     60
     61        x = 1
     62
     63    becomes
     64   
     65        load r[x], 1
     66   
     67    instead of
     68
     69        load r0, 1
     70        mov r[x], r0
     71   
     72    because the assignment node, "x =", passes r[x] as dst to the number node, "1".
     73*/
    5374
    5475// ------------------------------ ThrowableExpressionData --------------------------------
     
    6485}
    6586
    66 RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg)
     87RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message)
    6788{
    6889    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    69     RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
     90    RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
    7091    generator.emitThrow(exception);
    7192    return exception;
    7293}
    7394
    74 RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
    75 {
    76     UString message = msg;
    77     substitute(message, label.ustring());
     95RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
     96{
     97    UString message = messageTemplate;
     98    substitute(message, label);
    7899    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    79     RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
     100    RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
    80101    generator.emitThrow(exception);
    81102    return exception;
     103}
     104
     105inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
     106{
     107    return emitThrowError(generator, type, messageTemplate, label.ustring());
    82108}
    83109
     
    99125}
    100126
     127inline StatementNode* SourceElements::singleStatement() const
     128{
     129    size_t size = m_statements.size();
     130    return size == 1 ? m_statements[0] : 0;
     131}
     132
     133inline StatementNode* SourceElements::lastStatement() const
     134{
     135    size_t size = m_statements.size();
     136    return size ? m_statements[size - 1] : 0;
     137}
     138
    101139// ------------------------------ NullNode -------------------------------------
    102140
     
    123161    if (dst == generator.ignoredResult())
    124162        return 0;
    125     return generator.emitLoad(dst, m_double);
     163    return generator.emitLoad(dst, m_value);
    126164}
    127165
     
    141179    RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
    142180    if (!regExp->isValid())
    143         return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
     181        return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage());
    144182    if (dst == generator.ignoredResult())
    145183        return 0;
     
    597635RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    598636{
    599     return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
     637    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
     638        ? "Postfix ++ operator applied to value that is not a reference."
     639        : "Postfix -- operator applied to value that is not a reference.");
    600640}
    601641
     
    759799RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    760800{
    761     return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
     801    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
     802        ? "Prefix ++ operator applied to value that is not a reference."
     803        : "Prefix -- operator applied to value that is not a reference.");
    762804}
    763805
     
    12371279}
    12381280
    1239 // ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
    1240 
    1241 static inline void statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst)
    1242 {
    1243     size_t size = statements.size();
     1281// ------------------------------ SourceElements -------------------------------
     1282
     1283inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     1284{
     1285    size_t size = m_statements.size();
    12441286    for (size_t i = 0; i < size; ++i)
    1245         generator.emitNode(dst, statements[i]);
     1287        generator.emitNode(dst, m_statements[i]);
    12461288}
    12471289
    12481290// ------------------------------ BlockNode ------------------------------------
    12491291
     1292inline StatementNode* BlockNode::lastStatement() const
     1293{
     1294    return m_statements ? m_statements->lastStatement() : 0;
     1295}
     1296
    12501297RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    12511298{
    1252     statementListEmitCode(m_children, generator, dst);
     1299    if (m_statements)
     1300        m_statements->emitBytecode(generator, dst);
    12531301    return 0;
    12541302}
     
    15501598    generator.emitPopScope();
    15511599    return result;
     1600}
     1601
     1602// ------------------------------ CaseClauseNode --------------------------------
     1603
     1604inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     1605{
     1606    if (m_statements)
     1607        m_statements->emitBytecode(generator, dst);
    15521608}
    15531609
     
    16711727    for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
    16721728        generator.emitLabel(labelVector[i++].get());
    1673         statementListEmitCode(list->getClause()->children(), generator, dst);
     1729        list->getClause()->emitBytecode(generator, dst);
    16741730    }
    16751731
    16761732    if (m_defaultClause) {
    16771733        generator.emitLabel(defaultLabel.get());
    1678         statementListEmitCode(m_defaultClause->children(), generator, dst);
     1734        m_defaultClause->emitBytecode(generator, dst);
    16791735    }
    16801736
    16811737    for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
    16821738        generator.emitLabel(labelVector[i++].get());
    1683         statementListEmitCode(list->getClause()->children(), generator, dst);
     1739        list->getClause()->emitBytecode(generator, dst);
    16841740    }
    16851741    if (!m_defaultClause)
     
    18131869// -----------------------------ScopeNodeData ---------------------------
    18141870
    1815 ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants)
     1871ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
    18161872    : m_numConstants(numConstants)
     1873    , m_statements(statements)
    18171874{
    18181875    m_arena.swap(arena);
     
    18211878    if (funcStack)
    18221879        m_functionStack.swap(*funcStack);
    1823     if (children)
    1824         children->releaseContentsIntoVector(m_children);
    18251880}
    18261881
     
    18511906}
    18521907
     1908inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
     1909{
     1910    if (m_data->m_statements)
     1911        m_data->m_statements->emitBytecode(generator, dst);
     1912}
     1913
     1914StatementNode* ScopeNode::singleStatement() const
     1915{
     1916    return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
     1917}
     1918
    18531919// ------------------------------ ProgramNode -----------------------------
    18541920
     
    18751941    RefPtr<RegisterID> dstRegister = generator.newTemporary();
    18761942    generator.emitLoad(dstRegister.get(), jsUndefined());
    1877     statementListEmitCode(children(), generator, dstRegister.get());
     1943    emitStatementsBytecode(generator, dstRegister.get());
    18781944
    18791945    generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
     
    19061972    RefPtr<RegisterID> dstRegister = generator.newTemporary();
    19071973    generator.emitLoad(dstRegister.get(), jsUndefined());
    1908     statementListEmitCode(children(), generator, dstRegister.get());
     1974    emitStatementsBytecode(generator, dstRegister.get());
    19091975
    19101976    generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
     
    19832049{
    19842050    generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
    1985     statementListEmitCode(children(), generator, generator.ignoredResult());
    1986     if (children().size() && children().last()->isBlock()) {
    1987         BlockNode* blockNode = static_cast<BlockNode*>(children().last());
    1988         if (blockNode->children().size() && blockNode->children().last()->isReturnNode())
     2051    emitStatementsBytecode(generator, generator.ignoredResult());
     2052    StatementNode* singleStatement = this->singleStatement();
     2053    if (singleStatement && singleStatement->isBlock()) {
     2054        StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
     2055        if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
    19892056            return 0;
    19902057    }
  • trunk/JavaScriptCore/parser/Nodes.h

    r47519 r47571  
    3535#include "SymbolTable.h"
    3636#include <wtf/MathExtras.h>
    37 #include <wtf/OwnPtr.h>
    3837
    3938namespace JSC {
     
    4140    class ArgumentListNode;
    4241    class BytecodeGenerator;
    43     class CodeBlock;
    44     class EvalCodeBlock;
    45     class EvalExecutable;
    46     class FuncDeclNode;
    4742    class FunctionBodyNode;
    48     class FunctionCodeBlock;
    49     class JSFunction;
    50     class ProgramCodeBlock;
    51     class ProgramExecutable;
    5243    class PropertyListNode;
    5344    class ReadModifyResolveNode;
    5445    class RegisterID;
    5546    class ScopeChainNode;
     47    class ScopeNode;
    5648
    5749    typedef unsigned CodeFeatures;
     
    9183    namespace DeclarationStacks {
    9284        enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
    93         typedef Vector<std::pair<Identifier, unsigned> > VarStack;
     85        typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
    9486        typedef Vector<FunctionBodyNode*> FunctionStack;
    9587    }
     
    10193    };
    10294
     95    class ParserArenaFreeable {
     96    public:
     97        // ParserArenaFreeable objects are are freed when the arena is deleted.
     98        // Destructors are not called. Clients must not call delete on such objects.
     99        void* operator new(size_t, JSGlobalData*);
     100    };
     101
    103102    class ParserArenaDeletable {
    104     protected:
    105         ParserArenaDeletable() { }
    106 
    107103    public:
    108104        virtual ~ParserArenaDeletable() { }
    109105
    110         // Objects created with this version of new are deleted when the arena is deleted.
     106        // ParserArenaDeletable objects are deleted when the arena is deleted.
     107        // Clients must not call delete directly on such objects.
    111108        void* operator new(size_t, JSGlobalData*);
    112 
    113         // Objects created with this version of new are not deleted when the arena is deleted.
    114         // Other arrangements must be made.
    115         void* operator new(size_t);
    116 
    117         void operator delete(void*);
    118     };
    119 
    120     class ParserArenaRefCounted : public RefCountedCustomAllocated<ParserArenaRefCounted> {
     109    };
     110
     111    class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
    121112    protected:
    122113        ParserArenaRefCounted(JSGlobalData*);
     
    129120    };
    130121
    131     class Node : public ParserArenaDeletable {
     122    class Node : public ParserArenaFreeable {
    132123    protected:
    133124        Node(JSGlobalData*);
    134125
    135126    public:
    136         /*
    137             Return value: The register holding the production's value.
    138                      dst: An optional parameter specifying the most efficient
    139                           destination at which to store the production's value.
    140                           The callee must honor dst.
    141 
    142             dst provides for a crude form of copy propagation. For example,
    143 
    144             x = 1
    145 
    146             becomes
    147            
    148             load r[x], 1
    149            
    150             instead of
    151 
    152             load r0, 1
    153             mov r[x], r0
    154            
    155             because the assignment node, "x =", passes r[x] as dst to the number
    156             node, "1".
    157         */
    158         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) = 0;
     127        virtual ~Node() { }
     128
     129        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
    159130
    160131        int lineNo() const { return m_line; }
     
    165136
    166137    class ExpressionNode : public Node {
    167     public:
     138    protected:
    168139        ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType());
    169140
     141    public:
    170142        virtual bool isNumber() const { return false; }
    171143        virtual bool isString() const { return false; }
     
    185157        ResultType resultDescriptor() const { return m_resultType; }
    186158
    187         // This needs to be in public in order to compile using GCC 3.x
    188         typedef enum { EvalOperator, FunctionCall } CallerType;
    189 
    190159    private:
    191160        ResultType m_resultType;
     
    193162
    194163    class StatementNode : public Node {
    195     public:
     164    protected:
    196165        StatementNode(JSGlobalData*);
    197166
    198         void setLoc(int line0, int line1);
     167    public:
     168        void setLoc(int firstLine, int lastLine);
    199169        int firstLine() const { return lineNo(); }
    200170        int lastLine() const { return m_lastLine; }
     
    234204    class NumberNode : public ExpressionNode {
    235205    public:
    236         NumberNode(JSGlobalData*, double v);
    237 
    238         double value() const { return m_double; }
    239         void setValue(double d) { m_double = d; }
     206        NumberNode(JSGlobalData*, double value);
     207
     208        double value() const { return m_value; }
     209        void setValue(double value) { m_value = value; }
    240210
    241211    private:
     
    245215        virtual bool isPure(BytecodeGenerator&) const { return true; }
    246216
    247         double m_double;
     217        double m_value;
    248218    };
    249219
    250220    class StringNode : public ExpressionNode {
    251221    public:
    252         StringNode(JSGlobalData*, const Identifier& v);
     222        StringNode(JSGlobalData*, const Identifier&);
    253223
    254224        const Identifier& value() { return m_value; }
     225
     226    private:
    255227        virtual bool isPure(BytecodeGenerator&) const { return true; }
    256228
    257     private:
    258229        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    259230       
    260231        virtual bool isString() const { return true; }
    261232
    262         Identifier m_value;
     233        const Identifier& m_value;
    263234    };
    264235   
     
    292263    protected:
    293264        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg);
     265        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const UString&);
    294266        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&);
    295267
     
    367339        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    368340
    369         Identifier m_pattern;
    370         Identifier m_flags;
     341        const Identifier& m_pattern;
     342        const Identifier& m_flags;
    371343    };
    372344
     
    392364        virtual bool isResolveNode() const { return true; }
    393365
    394         Identifier m_ident;
     366        const Identifier& m_ident;
    395367        int32_t m_startOffset;
    396368    };
    397369
    398     class ElementNode : public ParserArenaDeletable {
     370    class ElementNode : public ParserArenaFreeable {
    399371    public:
    400372        ElementNode(JSGlobalData*, int elision, ExpressionNode*);
     
    429401    };
    430402
    431     class PropertyNode : public ParserArenaDeletable {
     403    class PropertyNode : public ParserArenaFreeable {
    432404    public:
    433405        enum Type { Constant, Getter, Setter };
     
    440412    private:
    441413        friend class PropertyListNode;
    442         Identifier m_name;
     414        const Identifier& m_name;
    443415        ExpressionNode* m_assign;
    444416        Type m_type;
     
    500472
    501473        ExpressionNode* m_base;
    502         Identifier m_ident;
     474        const Identifier& m_ident;
    503475    };
    504476
     
    515487    };
    516488
    517     class ArgumentsNode : public ParserArenaDeletable {
     489    class ArgumentsNode : public ParserArenaFreeable {
    518490    public:
    519491        ArgumentsNode(JSGlobalData*);
     
    563535        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    564536
    565         Identifier m_ident;
     537        const Identifier& m_ident;
    566538        ArgumentsNode* m_args;
    567539        size_t m_index; // Used by LocalVarFunctionCallNode.
     
    590562    protected:
    591563        ExpressionNode* m_base;
    592         const Identifier m_ident;
     564        const Identifier& m_ident;
    593565        ArgumentsNode* m_args;
    594566    };
     
    615587
    616588    protected:
    617         const Identifier m_ident;
     589        const Identifier& m_ident;
    618590    };
    619591
     
    648620
    649621        ExpressionNode* m_base;
    650         Identifier m_ident;
     622        const Identifier& m_ident;
    651623        Operator m_operator;
    652624    };
     
    670642        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    671643
    672         Identifier m_ident;
     644        const Identifier& m_ident;
    673645    };
    674646
     
    692664
    693665        ExpressionNode* m_base;
    694         Identifier m_ident;
     666        const Identifier& m_ident;
    695667    };
    696668
     
    724696        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    725697
    726         Identifier m_ident;
     698        const Identifier& m_ident;
    727699    };
    728700
     
    767739
    768740        ExpressionNode* m_base;
    769         Identifier m_ident;
     741        const Identifier& m_ident;
    770742        Operator m_operator;
    771743    };
     
    826798        BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
    827799
    828         RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
     800        RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
    829801
    830802    private:
     
    1009981        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    1010982
    1011         Identifier m_ident;
     983        const Identifier& m_ident;
    1012984        ExpressionNode* m_right;
    1013985        size_t m_index; // Used by ReadModifyLocalVarNode.
     
    1023995        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    1024996
    1025         Identifier m_ident;
     997        const Identifier& m_ident;
    1026998        ExpressionNode* m_right;
    1027999        size_t m_index; // Used by ReadModifyLocalVarNode.
     
    10661038
    10671039        ExpressionNode* m_base;
    1068         Identifier m_ident;
     1040        const Identifier& m_ident;
    10691041        ExpressionNode* m_right;
    10701042        bool m_rightHasAssignments;
     
    10791051
    10801052        ExpressionNode* m_base;
    1081         Identifier m_ident;
     1053        const Identifier& m_ident;
    10821054        ExpressionNode* m_right;
    10831055        Operator m_operator : 31;
     
    11231095        virtual RegisterID* emitCodeSingle(BytecodeGenerator&);
    11241096
    1125         Identifier m_ident;
     1097        const Identifier& m_ident;
    11261098
    11271099    public:
     
    11421114    };
    11431115
    1144     typedef Vector<StatementNode*> StatementVector;
    1145 
    11461116    class SourceElements : public ParserArenaDeletable {
    11471117    public:
     
    11491119
    11501120        void append(StatementNode*);
    1151         void releaseContentsIntoVector(StatementVector& destination)
    1152         {
    1153             ASSERT(destination.isEmpty());
    1154             m_statements.swap(destination);
    1155             destination.shrinkToFit();
    1156         }
    1157 
    1158     private:
    1159         StatementVector m_statements;
     1121
     1122        StatementNode* singleStatement() const;
     1123        StatementNode* lastStatement() const;
     1124
     1125        void emitBytecode(BytecodeGenerator&, RegisterID* destination);
     1126
     1127    private:
     1128        Vector<StatementNode*> m_statements;
    11601129    };
    11611130
    11621131    class BlockNode : public StatementNode {
    11631132    public:
    1164         BlockNode(JSGlobalData*, SourceElements* children);
    1165 
    1166         StatementVector& children() { return m_children; }
     1133        BlockNode(JSGlobalData*, SourceElements* = 0);
     1134
     1135        StatementNode* lastStatement() const;
    11671136
    11681137    private:
     
    11711140        virtual bool isBlock() const { return true; }
    11721141
    1173         StatementVector m_children;
     1142        SourceElements* m_statements;
    11741143    };
    11751144
     
    12811250        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    12821251
    1283         Identifier m_ident;
     1252        const Identifier& m_ident;
    12841253        ExpressionNode* m_init;
    12851254        ExpressionNode* m_lexpr;
     
    12971266        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    12981267
    1299         Identifier m_ident;
     1268        const Identifier& m_ident;
    13001269    };
    13011270
     
    13081277        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    13091278
    1310         Identifier m_ident;
     1279        const Identifier& m_ident;
    13111280    };
    13121281
     
    13431312        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    13441313
    1345         Identifier m_name;
     1314        const Identifier& m_name;
    13461315        StatementNode* m_statement;
    13471316    };
     
    13621331
    13631332    private:
    1364         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0);
     1333        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    13651334
    13661335        StatementNode* m_tryBlock;
    1367         Identifier m_exceptionIdent;
     1336        const Identifier& m_exceptionIdent;
    13681337        StatementNode* m_catchBlock;
    13691338        StatementNode* m_finallyBlock;
     
    13711340    };
    13721341
    1373     class ParameterNode : public ParserArenaDeletable {
     1342    class ParameterNode : public ParserArenaFreeable {
    13741343    public:
    13751344        ParameterNode(JSGlobalData*, const Identifier&);
     
    13801349
    13811350    private:
    1382         Identifier m_ident;
     1351        const Identifier& m_ident;
    13831352        ParameterNode* m_next;
    13841353    };
     
    13941363        FunctionStack m_functionStack;
    13951364        int m_numConstants;
    1396         StatementVector m_children;
     1365        SourceElements* m_statements;
    13971366    };
    13981367
     
    14041373        ScopeNode(JSGlobalData*);
    14051374        ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants);
     1375
     1376        using ParserArenaRefCounted::operator new;
    14061377
    14071378        void adoptData(std::auto_ptr<ScopeNodeData> data)
     
    14301401        FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
    14311402
    1432         StatementVector& children() { ASSERT(m_data); return m_data->m_children; }
    1433 
    14341403        int neededConstants()
    14351404        {
     
    14401409        }
    14411410
     1411        StatementNode* singleStatement() const;
     1412
     1413        void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
     1414
    14421415    protected:
    14431416        void setSource(const SourceCode& source) { m_source = source; }
     
    14881461        const Identifier& ident() { return m_ident; }
    14891462
    1490         void reparseDataIfNecessary(ScopeChainNode* scopeChainNode);
     1463        void reparseDataIfNecessary(ScopeChainNode*);
    14911464
    14921465    private:
     
    15241497    };
    15251498
    1526     class CaseClauseNode : public ParserArenaDeletable {
    1527     public:
    1528         CaseClauseNode(JSGlobalData*, ExpressionNode*);
    1529         CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements*);
     1499    class CaseClauseNode : public ParserArenaFreeable {
     1500    public:
     1501        CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements* = 0);
    15301502
    15311503        ExpressionNode* expr() const { return m_expr; }
    1532         StatementVector& children() { return m_children; }
    1533 
    1534     private:
    1535         ExpressionNode* m_expr;
    1536         StatementVector m_children;
    1537     };
    1538 
    1539     class ClauseListNode : public ParserArenaDeletable {
     1504
     1505        void emitBytecode(BytecodeGenerator&, RegisterID* destination);
     1506
     1507    private:
     1508        ExpressionNode* m_expr;
     1509        SourceElements* m_statements;
     1510    };
     1511
     1512    class ClauseListNode : public ParserArenaFreeable {
    15401513    public:
    15411514        ClauseListNode(JSGlobalData*, CaseClauseNode*);
     
    15501523    };
    15511524
    1552     class CaseBlockNode : public ParserArenaDeletable {
     1525    class CaseBlockNode : public ParserArenaFreeable {
    15531526    public:
    15541527        CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
    15551528
    1556         RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0);
     1529        RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination);
    15571530
    15581531    private:
  • trunk/JavaScriptCore/parser/Parser.cpp

    r44224 r47571  
    5454
    5555    Lexer& lexer = *globalData->lexer;
    56     lexer.setCode(*m_source);
     56    lexer.setCode(*m_source, m_arena);
    5757
    5858    int parseError = jscyyparse(globalData);
  • trunk/JavaScriptCore/parser/Parser.h

    r47307 r47571  
    2828#include "JSGlobalObject.h"
    2929#include "Nodes.h"
     30#include "ParserArena.h"
    3031#include "SourceProvider.h"
    3132#include <wtf/Forward.h>
     
    126127    {
    127128        RefPtr<ProgramNode> program = parse<ProgramNode>(exec, debugger, source, errLine, errMsg);
    128 
    129129        if (!program)
    130130            return 0;
    131131
    132         StatementVector& children = program->children();
    133         if (children.size() != 1)
    134             return 0;
    135 
    136         StatementNode* exprStatement = children[0];
     132        StatementNode* exprStatement = program->singleStatement();
    137133        ASSERT(exprStatement);
    138134        ASSERT(exprStatement->isExprStatement());
     
    146142            return 0;
    147143
    148         RefPtr<FunctionBodyNode> body = static_cast<FuncExprNode*>(funcExpr)->body();
     144        FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
    149145        ASSERT(body);
    150         return body.release();
     146        return body;
    151147    }
    152148
  • trunk/JavaScriptCore/parser/ParserArena.cpp

    r43661 r47571  
    3131namespace JSC {
    3232
     33ParserArena::ParserArena()
     34    : m_freeableMemory(0)
     35    , m_freeablePoolEnd(0)
     36    , m_identifierArena(new IdentifierArena)
     37{
     38}
     39
     40inline void* ParserArena::freeablePool()
     41{
     42    ASSERT(m_freeablePoolEnd);
     43    return m_freeablePoolEnd - freeablePoolSize;
     44}
     45
     46inline void ParserArena::deallocateObjects()
     47{
     48    if (m_freeablePoolEnd)
     49        fastFree(freeablePool());
     50
     51    size_t size = m_freeablePools.size();
     52    for (size_t i = 0; i < size; ++i)
     53        fastFree(m_freeablePools[i]);
     54
     55    size = m_deletableObjects.size();
     56    for (size_t i = 0; i < size; ++i) {
     57        ParserArenaDeletable* object = m_deletableObjects[i];
     58        object->~ParserArenaDeletable();
     59        fastFree(object);
     60    }
     61}
     62
    3363ParserArena::~ParserArena()
    3464{
    35     deleteAllValues(m_deletableObjects);
     65    deallocateObjects();
    3666}
    3767
     
    5383void ParserArena::reset()
    5484{
    55     deleteAllValues(m_deletableObjects);
    56     m_deletableObjects.shrink(0);
    57     m_refCountedObjects.shrink(0);
     85    // Since this code path is used only when parsing fails, it's not bothering to reuse
     86    // any of the memory the arena allocated. We could improve that later if we want to
     87    // efficiently reuse the same arena.
     88
     89    deallocateObjects();
     90
     91    m_freeableMemory = 0;
     92    m_freeablePoolEnd = 0;
     93    m_identifierArena->clear();
     94    m_freeablePools.clear();
     95    m_deletableObjects.clear();
     96    m_refCountedObjects.clear();
     97}
     98
     99void ParserArena::allocateFreeablePool()
     100{
     101    if (m_freeablePoolEnd)
     102        m_freeablePools.append(freeablePool());
     103
     104    char* pool = static_cast<char*>(fastMalloc(freeablePoolSize));
     105    m_freeableMemory = pool;
     106    m_freeablePoolEnd = pool + freeablePoolSize;
     107    ASSERT(freeablePool() == pool);
     108}
     109
     110bool ParserArena::isEmpty() const
     111{
     112    return !m_freeablePoolEnd
     113        && m_identifierArena->isEmpty()
     114        && m_freeablePools.isEmpty()
     115        && m_deletableObjects.isEmpty()
     116        && m_refCountedObjects.isEmpty();
    58117}
    59118
  • trunk/JavaScriptCore/parser/ParserArena.h

    r43661 r47571  
    2727#define ParserArena_h
    2828
    29 #include <wtf/PassRefPtr.h>
    30 #include <wtf/RefPtr.h>
    31 #include <wtf/Vector.h>
     29#include "Identifier.h"
     30#include <wtf/SegmentedVector.h>
    3231
    3332namespace JSC {
     
    3635    class ParserArenaRefCounted;
    3736
    38     class ParserArena {
     37    class IdentifierArena {
    3938    public:
     39        ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length);
     40        const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
     41
     42        void clear() { m_identifiers.clear(); }
     43        bool isEmpty() const { return m_identifiers.isEmpty(); }
     44
     45    private:
     46        typedef SegmentedVector<Identifier, 64> IdentifierVector;
     47        IdentifierVector m_identifiers;
     48    };
     49
     50    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const UChar* characters, size_t length)
     51    {
     52        m_identifiers.append(Identifier(globalData, characters, length));
     53        return m_identifiers.last();
     54    }
     55
     56    inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number)
     57    {
     58        m_identifiers.append(Identifier(globalData, UString::from(number)));
     59        return m_identifiers.last();
     60    }
     61
     62    class ParserArena : Noncopyable {
     63    public:
     64        ParserArena();
     65        ~ParserArena();
     66
    4067        void swap(ParserArena& otherArena)
    4168        {
     69            std::swap(m_freeableMemory, otherArena.m_freeableMemory);
     70            std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd);
     71            m_identifierArena.swap(otherArena.m_identifierArena);
     72            m_freeablePools.swap(otherArena.m_freeablePools);
    4273            m_deletableObjects.swap(otherArena.m_deletableObjects);
    4374            m_refCountedObjects.swap(otherArena.m_refCountedObjects);
    4475        }
    45         ~ParserArena();
    4676
    47         void deleteWithArena(ParserArenaDeletable* object) { m_deletableObjects.append(object); }
     77        void* allocateFreeable(size_t size)
     78        {
     79            ASSERT(size);
     80            ASSERT(size <= freeablePoolSize);
     81            size_t alignedSize = alignSize(size);
     82            ASSERT(alignedSize <= freeablePoolSize);
     83            if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd - m_freeableMemory) < alignedSize))
     84                allocateFreeablePool();
     85            void* block = m_freeableMemory;
     86            m_freeableMemory += alignedSize;
     87            return block;
     88        }
     89
     90        void* allocateDeletable(size_t size)
     91        {
     92            ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size));
     93            m_deletableObjects.append(deletable);
     94            return deletable;
     95        }
     96
    4897        void derefWithArena(PassRefPtr<ParserArenaRefCounted> object) { m_refCountedObjects.append(object); }
    49 
    5098        bool contains(ParserArenaRefCounted*) const;
    5199        ParserArenaRefCounted* last() const;
    52100        void removeLast();
    53101
    54         bool isEmpty() const { return m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); }
     102        bool isEmpty() const;
    55103        void reset();
    56104
     105        IdentifierArena& identifierArena() { return *m_identifierArena; }
     106
    57107    private:
     108        static const size_t freeablePoolSize = 8000;
     109
     110        static size_t alignSize(size_t size)
     111        {
     112            return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1);
     113        }
     114
     115        void* freeablePool();
     116        void allocateFreeablePool();
     117        void deallocateObjects();
     118
     119        char* m_freeableMemory;
     120        char* m_freeablePoolEnd;
     121
     122        OwnPtr<IdentifierArena> m_identifierArena;
     123        Vector<void*> m_freeablePools;
    58124        Vector<ParserArenaDeletable*> m_deletableObjects;
    59125        Vector<RefPtr<ParserArenaRefCounted> > m_refCountedObjects;
Note: See TracChangeset for help on using the changeset viewer.