Changeset 47571 in webkit for trunk/JavaScriptCore/parser/Nodes.h


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.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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:
Note: See TracChangeset for help on using the changeset viewer.