Ignore:
Timestamp:
Oct 28, 2007, 7:00:57 PM (18 years ago)
Author:
ggaren
Message:

Reviewed by Maciej Stachowiak, Darin Adler.


Much supporting work done by Maciej Stachowiak, Maks Orlovich, and
Cameron Zwarich.


AST transfom to replace slow resolve nodes with fast local variable
alternatives that do direct memory access. Currently, only ResolveNode
provides a fast local variable alternative. 6 others are soon to come.


16.7% speedup on SunSpider.


Most of this patch is just scaffolding to support iterating all the
resolve nodes in the AST through optimizeResolveNodes(). In
optimizeResolveNodes(), most classes just push their child nodes onto
the processing stack, while ResolveNodes actually replace themselves in
the tree with more optimized alternatives, if possible.

Here are the interesting bits:

  • kjs/nodes.h: Added PlacementNewAdoptTag, along with implementations in Node and ResolveNode. This tag allows you to use placement new to swap out a base class Node in favor of a subclass copy that holds the same data. (Without this tag, default initialization would NULL out RefPtrs, change line numbers, etc.)
  • kjs/nodes.cpp: (KJS::ResolveNode::evaluate): Since we're taking the slow path, ASSERT that the fast path is impossible, to make sure we didn't leave anything on the table.

(KJS::FunctionBodyNode::optimizeResolveNodes): Here's where the AST
transformation happens.


(KJS::ResolveNode::optimizeResolveNodes): Here's where the ResolveNode
optimization happens.

  • kjs/function.h: Added symbolTable() accessor for, for the sake of an ASSERT.
File:
1 edited

Legend:

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

    r27198 r27199  
    393393ActivationImp::ActivationImp(FunctionImp* function, const List& arguments)
    394394    : d(new ActivationImpPrivate(function, arguments))
    395     , symbolTable(&function->body->symbolTable())
     395    , m_symbolTable(&function->body->symbolTable())
    396396{
    397397}
     
    423423    // it's more efficient to just get and check for a special empty
    424424    // value than to do a separate contains check
    425     size_t index = symbolTable->get(propertyName.ustring().rep());
     425    size_t index = m_symbolTable->get(propertyName.ustring().rep());
    426426    if (index != missingSymbolMarker()) {
    427427        slot.setValueSlot(this, &d->localStorage[index].value);
     
    448448        return false;
    449449
    450     if (symbolTable->contains(propertyName.ustring().rep()))
     450    if (m_symbolTable->contains(propertyName.ustring().rep()))
    451451        return false;
    452452
     
    462462  // it's more efficient to just get and check for a special empty
    463463  // value than to do a separate contains check
    464   size_t index = symbolTable->get(propertyName.ustring().rep());
     464  size_t index = m_symbolTable->get(propertyName.ustring().rep());
    465465  if (index != missingSymbolMarker()) {
    466466    LocalStorageEntry& entry = d->localStorage[index];
Note: See TracChangeset for help on using the changeset viewer.