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).
(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.
(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.
(JSC::JITThunks::tryCachePutByID):
(JSC::JITThunks::tryCacheGetByID): Updated for rename to
"normalizePrototypeChain" and removal of "isCacheable".
(JSC::DEFINE_STUB_FUNCTION):
(JSC::): Added has_property and to_object stubs. Removed op_next_pname
stub, since has_property is all we need anymore.
(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.
(JSC::asCell):
- runtime/MarkStack.h: Make those mischievous #include gods happy.
- runtime/ObjectConstructor.cpp:
(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.
(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.