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


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

Reviewed by Oliver Hunt.


AST optimization: Avoid NULL-checking ForNode's child nodes.


0.6% speedup on SunSpider.


This is a proof of concept patch that demonstrates how to optimize
grammar productions with optional components, like


for (optional; optional; optional) {

...

}


The parser emits NULL for an optional component that is not present.

Instead of checking for a NULL child at execution time, a node that
expects an optional component to be present more often than not checks
for a NULL child at construction time, and substitutes a viable
alternative node in its place.

(We'd like the parser to start emitting NULL a lot more once we teach
it to emit NULL for certain no-op productions like EmptyStatement and
VariableStatement, so, as a foundation, it's important for nodes with
NULL optional components to be fast.)

  • kjs/Parser.cpp: (KJS::Parser::didFinishParsing): Check for NULL SourceElements. Also, moved didFinishParsing into the .cpp file because adding a branch while it was in the header file caused a substantial and inexplicable performance regression. (Did I mention that GCC is crazy?)
  • kjs/grammar.y:
  • kjs/nodes.cpp: (KJS::BlockNode::BlockNode): Check for NULL SourceElements. (KJS::ForNode::optimizeVariableAccess): No need to check for NULL here. (KJS::ForNode::execute): No need to check for NULL here.
  • kjs/nodes.h: (KJS::ForNode::): Check for NULL SourceElements. Substitute a TrueNode because it's semantically harmless, and it evaluates to boolean in an efficient manner.
File:
1 edited

Legend:

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

    r28907 r28923  
    36063606
    36073607BlockNode::BlockNode(SourceElements* children)
    3608     : m_children(children)
     3608    : m_children(children ? children : new SourceElements)
    36093609{
    36103610    ASSERT(m_children);
     
    37733773{
    37743774    nodeStack.append(statement.get());
    3775     if (expr3)
    3776         nodeStack.append(expr3.get());
    3777     if (expr2)
    3778         nodeStack.append(expr2.get());
    3779     if (expr1)
    3780         nodeStack.append(expr1.get());
     3775    nodeStack.append(expr3.get());
     3776    nodeStack.append(expr2.get());
     3777    nodeStack.append(expr1.get());
    37813778}
    37823779
     
    37863783    JSValue* value = 0;
    37873784
    3788     if (expr1) {
    3789         expr1->evaluate(exec);
     3785    expr1->evaluate(exec);
     3786    KJS_CHECKEXCEPTION
     3787
     3788    while (1) {
     3789        bool b = expr2->evaluateToBoolean(exec);
    37903790        KJS_CHECKEXCEPTION
    3791     }
    3792 
    3793     while (1) {
    3794         if (expr2) {
    3795             bool b = expr2->evaluateToBoolean(exec);
    3796             KJS_CHECKEXCEPTION
    3797             if (!b)
    3798                 break;
    3799         }
     3791        if (!b)
     3792            break;
    38003793
    38013794        exec->pushIteration();
     
    38173810
    38183811continueForLoop:
    3819         if (expr3) {
    3820             expr3->evaluate(exec);
    3821             KJS_CHECKEXCEPTION
    3822         }
     3812        expr3->evaluate(exec);
     3813        KJS_CHECKEXCEPTION
    38233814    }
    38243815 
Note: See TracChangeset for help on using the changeset viewer.