Ignore:
Timestamp:
Oct 16, 2009, 5:28:19 PM (16 years ago)
Author:
[email protected]
Message:

Fast for-in enumeration: Cache JSPropertyNameIterator; cache JSStrings
in JSPropertyNameIterator; inline more code.

Patch by Geoffrey Garen <[email protected]> on 2009-10-16
Reviewed by Oliver Hunt.

1.024x as fast on SunSpider (fasta: 1.43x as fast).

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):

  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitGetPropertyNames):
(JSC::BytecodeGenerator::emitNextPropertyName):

  • bytecompiler/BytecodeGenerator.h: Added a few extra operands to

op_get_pnames and op_next_pname so that we can track iteration state
in the register file instead of in the JSPropertyNameIterator. (To be
cacheable, the JSPropertyNameIterator must be stateless.)

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::tryCachePutByID):
(JSC::Interpreter::tryCacheGetByID): Updated for rename to
"normalizePrototypeChain" and removal of "isCacheable".

(JSC::Interpreter::privateExecute): Updated for in-RegisterFile
iteration state tracking.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_get_pnames): Updated for in-RegisterFile
iteration state tracking.

(JSC::JIT::emit_op_next_pname): Inlined code generation for op_next_pname.

  • jit/JITStubs.cpp:

(JSC::JITThunks::tryCachePutByID):
(JSC::JITThunks::tryCacheGetByID): Updated for rename to
"normalizePrototypeChain" and removal of "isCacheable".

(JSC::DEFINE_STUB_FUNCTION):

  • jit/JITStubs.h:

(JSC::): Added has_property and to_object stubs. Removed op_next_pname
stub, since has_property is all we need anymore.

  • parser/Nodes.cpp:

(JSC::ForInNode::emitBytecode): Updated for in-RegisterFile
iteration state tracking.

  • runtime/JSCell.h:
  • runtime/JSObject.cpp:

(JSC::JSObject::getPropertyNames): Don't do caching at this layer
anymore, since we don't create a JSPropertyNameIterator at this layer.

  • runtime/JSPropertyNameIterator.cpp:

(JSC::JSPropertyNameIterator::create): Do do caching at this layer.
(JSC::JSPropertyNameIterator::get): Updated for in-RegisterFile
iteration state tracking.
(JSC::JSPropertyNameIterator::markChildren): Mark our JSStrings.

  • runtime/JSPropertyNameIterator.h:

(JSC::JSPropertyNameIterator::size):
(JSC::JSPropertyNameIterator::setCachedStructure):
(JSC::JSPropertyNameIterator::cachedStructure):
(JSC::JSPropertyNameIterator::setCachedPrototypeChain):
(JSC::JSPropertyNameIterator::cachedPrototypeChain):
(JSC::JSPropertyNameIterator::JSPropertyNameIterator):
(JSC::Structure::setEnumerationCache): Don't store iteration state in
a JSPropertyNameIterator. Do cache a JSPropertyNameIterator in a
Structure.

  • runtime/JSValue.h:

(JSC::asCell):

  • runtime/MarkStack.h: Make those mischievous #include gods happy.
  • runtime/ObjectConstructor.cpp:
  • runtime/Operations.h:

(JSC::normalizePrototypeChain): Renamed countPrototypeChainEntriesAndCheckForProxies
to normalizePrototypeChain, since it changes dictionary prototypes to
non-dictionary objects.

  • runtime/PropertyNameArray.cpp:

(JSC::PropertyNameArray::add):

  • runtime/PropertyNameArray.h:

(JSC::PropertyNameArrayData::PropertyNameArrayData):
(JSC::PropertyNameArray::data):
(JSC::PropertyNameArray::size):
(JSC::PropertyNameArray::begin):
(JSC::PropertyNameArray::end): Simplified some code here to help with
current and future refactoring.

  • runtime/Protect.h:
  • runtime/Structure.cpp:

(JSC::Structure::~Structure):
(JSC::Structure::addPropertyWithoutTransition):
(JSC::Structure::removePropertyWithoutTransition): No need to clear
the enumeration cache with adding / removing properties without
transition. It is an error to add / remove properties without transition
once an object has been observed, and we can ASSERT to catch that.

  • runtime/Structure.h:

(JSC::Structure::enumerationCache): Changed the enumeration cache to
hold a JSPropertyNameIterator.

  • runtime/StructureChain.cpp:
  • runtime/StructureChain.h:

(JSC::StructureChain::head): Removed StructureChain::isCacheable because
it was wrong-headed in two ways: (1) It gave up when a prototype was a
dictionary, but instead we want un-dictionary heavily accessed
prototypes; (2) It folded a test for hasDefaultGetPropertyNames() into
a generic test for "cacheable-ness", but hasDefaultGetPropertyNames()
is only releavant to for-in caching.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/PropertyNameArray.h

    r49398 r49717  
    2525#include "Identifier.h"
    2626#include <wtf/HashSet.h>
     27#include <wtf/OwnArrayPtr.h>
    2728#include <wtf/Vector.h>
    2829
     
    3233    class StructureChain;
    3334
     35    // FIXME: Rename to PropertyNameArray.
    3436    class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
    3537    public:
    3638        typedef Vector<Identifier, 20> PropertyNameVector;
    37         typedef PropertyNameVector::const_iterator const_iterator;
    3839
    3940        static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
    4041
    41         const_iterator begin() const { return m_propertyNameVector.begin(); }
    42         const_iterator end() const { return m_propertyNameVector.end(); }
    43 
    4442        PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
    45 
    46         void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
    47         Structure* cachedStructure() const { return m_cachedStructure; }
    48 
    49         void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
    50         StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
    5143
    5244    private:
    5345        PropertyNameArrayData()
    54             : m_cachedStructure(0)
    5546        {
    5647        }
    5748
    5849        PropertyNameVector m_propertyNameVector;
    59         Structure* m_cachedStructure;
    60         RefPtr<StructureChain> m_cachedPrototypeChain;
    6150    };
    6251
     52    // FIXME: Rename to PropertyNameArrayBuilder.
    6353    class PropertyNameArray {
    6454    public:
    65         typedef PropertyNameArrayData::const_iterator const_iterator;
    66 
    6755        PropertyNameArray(JSGlobalData* globalData)
    6856            : m_data(PropertyNameArrayData::create())
     
    8573        void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
    8674
    87         size_t size() const { return m_data->propertyNameVector().size(); }
    88 
    8975        Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
    9076        const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
    9177
    92         const_iterator begin() const { return m_data->begin(); }
    93         const_iterator end() const { return m_data->end(); }
    94 
    9578        void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
    9679        PropertyNameArrayData* data() { return m_data.get(); }
    97 
    9880        PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
    9981
    100         void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; }
    101         bool shouldCache() const { return m_shouldCache; }
     82        // FIXME: Remove these functions.
     83        typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
     84        size_t size() const { return m_data->propertyNameVector().size(); }
     85        const_iterator begin() const { return m_data->propertyNameVector().begin(); }
     86        const_iterator end() const { return m_data->propertyNameVector().end(); }
    10287
    10388    private:
Note: See TracChangeset for help on using the changeset viewer.