Changeset 28854 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Dec 18, 2007, 11:42:29 PM (17 years ago)
Author:
[email protected]
Message:

Replace post-parse pass to find declarations with logic in the parser itself

Reviewed by Geoff.

Instead of finding declarations in a pass following the initial parsing of
a program, we incorporate the logic directly into the parser. This lays
the groundwork for further optimisations (such as improving performance in
declaration expressions -- var x = y; -- to match that of standard assignment)
in addition to providing a 0.4% performance improvement in SunSpider.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r28608 r28854  
    111111static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
    112112
    113 struct NodeCounter {
     113struct ParserRefCountedCounter {
    114114    static unsigned count;
    115     ~NodeCounter()
     115    ParserRefCountedCounter()
    116116    {
    117117        if (count)
     
    119119    }
    120120};
    121 unsigned NodeCounter::count = 0;
    122 static NodeCounter nodeCounter;
     121unsigned ParserRefCountedCounter::count = 0;
     122static ParserRefCountedCounter parserRefCountedCounter;
    123123#endif
    124124
    125 static HashSet<Node*>* newNodes;
    126 static HashCountedSet<Node*>* nodeExtraRefCounts;
     125static HashSet<ParserRefCounted*>* newTrackedObjects;
     126static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
     127
     128ParserRefCounted::ParserRefCounted()
     129{
     130#ifndef NDEBUG
     131    ++ParserRefCountedCounter::count;
     132#endif
     133  if (!newTrackedObjects)
     134      newTrackedObjects = new HashSet<ParserRefCounted*>;
     135  newTrackedObjects->add(this);
     136  ASSERT(newTrackedObjects->contains(this));
     137}
     138
     139ParserRefCounted::~ParserRefCounted()
     140{
     141#ifndef NDEBUG
     142    --ParserRefCountedCounter::count;
     143#endif
     144}
     145
     146void ParserRefCounted::ref()
     147{
     148    // bumping from 0 to 1 is just removing from the new nodes set
     149    if (newTrackedObjects) {
     150        HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
     151        if (it != newTrackedObjects->end()) {
     152            newTrackedObjects->remove(it);
     153            ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
     154            return;
     155        }
     156    }   
     157
     158    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
     159   
     160    if (!trackedObjectExtraRefCounts)
     161        trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
     162    trackedObjectExtraRefCounts->add(this);
     163}
     164
     165void ParserRefCounted::deref()
     166{
     167    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
     168   
     169    if (!trackedObjectExtraRefCounts) {
     170        delete this;
     171        return;
     172    }
     173
     174    HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
     175    if (it == trackedObjectExtraRefCounts->end())
     176        delete this;
     177    else
     178        trackedObjectExtraRefCounts->remove(it);
     179}
     180
     181unsigned ParserRefCounted::refcount()
     182{
     183    if (newTrackedObjects && newTrackedObjects->contains(this)) {
     184        ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
     185        return 0;
     186    }
     187 
     188    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
     189
     190    if (!trackedObjectExtraRefCounts)
     191        return 1;
     192
     193    return 1 + trackedObjectExtraRefCounts->count(this);
     194}
     195
     196void ParserRefCounted::deleteNewObjects()
     197{
     198    if (!newTrackedObjects)
     199        return;
     200
     201#ifndef NDEBUG
     202    HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
     203    for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
     204        ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
     205#endif
     206    deleteAllValues(*newTrackedObjects);
     207    delete newTrackedObjects;
     208    newTrackedObjects = 0;
     209}
    127210
    128211Node::Node()
     
    130213    , m_expectedReturnType(ObjectType)
    131214{
    132 #ifndef NDEBUG
    133     ++NodeCounter::count;
    134 #endif
    135215  m_line = lexer().lineNo();
    136   if (!newNodes)
    137       newNodes = new HashSet<Node*>;
    138   newNodes->add(this);
    139216}
    140217
     
    143220    , m_expectedReturnType(expectedReturn)
    144221{
    145 #ifndef NDEBUG
    146     ++NodeCounter::count;
    147 #endif
    148222    m_line = lexer().lineNo();
    149     if (!newNodes)
    150         newNodes = new HashSet<Node*>;
    151     newNodes->add(this);
    152 }
    153 
    154 Node::~Node()
    155 {
    156 #ifndef NDEBUG
    157     --NodeCounter::count;
    158 #endif
    159 }
    160 
    161 void Node::ref()
    162 {
    163     // bumping from 0 to 1 is just removing from the new nodes set
    164     if (newNodes) {
    165         HashSet<Node*>::iterator it = newNodes->find(this);
    166         if (it != newNodes->end()) {
    167             newNodes->remove(it);
    168             ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
    169             return;
    170         }
    171     }   
    172 
    173     ASSERT(!newNodes || !newNodes->contains(this));
    174    
    175     if (!nodeExtraRefCounts)
    176         nodeExtraRefCounts = new HashCountedSet<Node*>;
    177     nodeExtraRefCounts->add(this);
    178 }
    179 
    180 void Node::deref()
    181 {
    182     ASSERT(!newNodes || !newNodes->contains(this));
    183    
    184     if (!nodeExtraRefCounts) {
    185         delete this;
    186         return;
    187     }
    188 
    189     HashCountedSet<Node*>::iterator it = nodeExtraRefCounts->find(this);
    190     if (it == nodeExtraRefCounts->end())
    191         delete this;
    192     else
    193         nodeExtraRefCounts->remove(it);
    194 }
    195 
    196 unsigned Node::refcount()
    197 {
    198     if (newNodes && newNodes->contains(this)) {
    199         ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
    200         return 0;
    201     }
    202  
    203     ASSERT(!newNodes || !newNodes->contains(this));
    204 
    205     if (!nodeExtraRefCounts)
    206         return 1;
    207 
    208     return 1 + nodeExtraRefCounts->count(this);
    209 }
    210 
    211 void Node::clearNewNodes()
    212 {
    213     if (!newNodes)
    214         return;
    215 
    216 #ifndef NDEBUG
    217     HashSet<Node*>::iterator end = newNodes->end();
    218     for (HashSet<Node*>::iterator it = newNodes->begin(); it != end; ++it)
    219         ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(*it));
    220 #endif
    221     deleteAllValues(*newNodes);
    222     delete newNodes;
    223     newNodes = 0;
    224223}
    225224
     
    44014400// ------------------------------ FunctionBodyNode -----------------------------
    44024401
    4403 ScopeNode::ScopeNode(SourceElements* children)
     4402ScopeNode::ScopeNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
    44044403    : BlockNode(children)
    44054404    , m_sourceURL(parser().sourceURL())
    44064405    , m_sourceId(parser().sourceId())
    44074406{
    4408 }
    4409 
    4410 ProgramNode::ProgramNode(SourceElements* children)
    4411     : ScopeNode(children)
    4412 {
    4413 }
    4414 
    4415 EvalNode::EvalNode(SourceElements* children)
    4416     : ScopeNode(children)
    4417 {
    4418 }
    4419 
    4420 FunctionBodyNode::FunctionBodyNode(SourceElements* children)
    4421     : ScopeNode(children)
     4407    if (varStack)
     4408        m_varStack = *varStack;
     4409
     4410    if (funcStack)
     4411        m_functionStack = *funcStack;
     4412}
     4413
     4414ProgramNode::ProgramNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     4415    : ScopeNode(children, varStack, funcStack)
     4416{
     4417}
     4418
     4419EvalNode::EvalNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     4420    : ScopeNode(children, varStack, funcStack)
     4421{
     4422}
     4423
     4424FunctionBodyNode::FunctionBodyNode(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
     4425    : ScopeNode(children, varStack, funcStack)
    44224426    , m_initialized(false)
    44234427{
    44244428}
    44254429
    4426 void ScopeNode::initializeDeclarationStacks(ExecState* exec)
    4427 {
    4428     DeclarationStacks::NodeStack nodeStack;
    4429     DeclarationStacks stacks(exec, nodeStack, m_varStack, m_functionStack);
    4430     Node* node = statementListInitializeDeclarationStack(*m_children, nodeStack);
    4431     if (!node)
    4432         return;
    4433    
    4434     while (true) {
    4435         ASSERT(node->mayHaveDeclarations()); // Otherwise, we wasted time putting an irrelevant node on the stack.
    4436         node->getDeclarations(stacks);
    4437        
    4438         size_t size = nodeStack.size();
    4439         if (!size)
    4440             break;
    4441         --size;
    4442         node = nodeStack[size];
    4443         nodeStack.shrink(size);
    4444     }
    4445 }
    4446 
    4447 void FunctionBodyNode::initializeSymbolTable()
     4430void FunctionBodyNode::initializeSymbolTable(ExecState* exec)
    44484431{
    44494432    size_t i, size;
     
    44514434
    44524435    // The order of additions here implicitly enforces the mutual exclusion described in ECMA 10.1.3.
    4453     for (i = 0, size = m_varStack.size(); i < size; ++i)
    4454         m_symbolTable.set(m_varStack[i]->ident.ustring().rep(), count++);
     4436    for (i = 0, size = m_varStack.size(); i < size; ++i) {
     4437        if (m_varStack[i]->ident != exec->propertyNames().arguments)
     4438            m_symbolTable.set(m_varStack[i]->ident.ustring().rep(), count);
     4439        count++;
     4440    }
    44554441
    44564442    for (i = 0, size = m_parameters.size(); i < size; ++i)
     
    44834469{
    44844470    if (!m_initialized) {
    4485         initializeDeclarationStacks(exec);
    4486         initializeSymbolTable();
     4471        initializeSymbolTable(exec);
    44874472        optimizeVariableAccess();
    44884473       
     
    45214506void ProgramNode::processDeclarations(ExecState* exec)
    45224507{
    4523     initializeDeclarationStacks(exec);
    4524 
    45254508    size_t i, size;
    45264509
     
    45474530void EvalNode::processDeclarations(ExecState* exec)
    45484531{
    4549     initializeDeclarationStacks(exec);
    4550 
    45514532    size_t i, size;
    45524533
Note: See TracChangeset for help on using the changeset viewer.