Changeset 171605 in webkit


Ignore:
Timestamp:
Jul 25, 2014, 11:46:46 AM (11 years ago)
Author:
[email protected]
Message:

Refactor our current implementation of for-in
https://bugs.webkit.org/show_bug.cgi?id=134142

Reviewed by Filip Pizlo.

Source/JavaScriptCore:
This patch splits for-in loops into three distinct parts:

  • Iterating over the indexed properties in the base object.
  • Iterating over the Structure properties in the base object.
  • Iterating over any other enumerable properties for that object and any objects in the prototype chain.


It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to
support the various operations required for each loop.

  • API/JSCallbackObjectFunctions.h:

(JSC::JSCallbackObject<Parent>::getOwnNonIndexPropertyNames):

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CallLinkStatus.h:

(JSC::CallLinkStatus::CallLinkStatus):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitGetByVal):
(JSC::BytecodeGenerator::emitComplexPopScopes):
(JSC::BytecodeGenerator::emitGetEnumerableLength):
(JSC::BytecodeGenerator::emitHasGenericProperty):
(JSC::BytecodeGenerator::emitHasIndexedProperty):
(JSC::BytecodeGenerator::emitHasStructureProperty):
(JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator):
(JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator):
(JSC::BytecodeGenerator::emitNextEnumeratorPropertyName):
(JSC::BytecodeGenerator::emitToIndexString):
(JSC::BytecodeGenerator::pushIndexedForInScope):
(JSC::BytecodeGenerator::popIndexedForInScope):
(JSC::BytecodeGenerator::pushStructureForInScope):
(JSC::BytecodeGenerator::popStructureForInScope):
(JSC::BytecodeGenerator::invalidateForInContextForLocal):

  • bytecompiler/BytecodeGenerator.h:

(JSC::ForInContext::ForInContext):
(JSC::ForInContext::~ForInContext):
(JSC::ForInContext::isValid):
(JSC::ForInContext::invalidate):
(JSC::ForInContext::local):
(JSC::StructureForInContext::StructureForInContext):
(JSC::StructureForInContext::type):
(JSC::StructureForInContext::index):
(JSC::StructureForInContext::property):
(JSC::StructureForInContext::enumerator):
(JSC::IndexedForInContext::IndexedForInContext):
(JSC::IndexedForInContext::type):
(JSC::IndexedForInContext::index):
(JSC::BytecodeGenerator::pushOptimisedForIn): Deleted.
(JSC::BytecodeGenerator::popOptimisedForIn): Deleted.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::ForInNode::tryGetBoundLocal):
(JSC::ForInNode::emitLoopHeader):
(JSC::ForInNode::emitMultiLoopBytecode):
(JSC::ForInNode::emitBytecode):

  • debugger/DebuggerScope.h:
  • dfg/DFGAbstractHeap.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGHeapLocation.cpp:

(WTF::printInternal):

  • dfg/DFGHeapLocation.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasArrayMode):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:

(JSC::JIT::compileHasIndexedProperty):
(JSC::JIT::emitInt32Load):

  • jit/JITInlines.h:

(JSC::JIT::emitDoubleGetByVal):
(JSC::JIT::emitLoadForArrayMode):
(JSC::JIT::emitContiguousGetByVal):
(JSC::JIT::emitArrayStorageGetByVal):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_get_enumerable_length):
(JSC::JIT::emit_op_has_structure_property):
(JSC::JIT::emitSlow_op_has_structure_property):
(JSC::JIT::emit_op_has_generic_property):
(JSC::JIT::privateCompileHasIndexedProperty):
(JSC::JIT::emit_op_has_indexed_property):
(JSC::JIT::emitSlow_op_has_indexed_property):
(JSC::JIT::emit_op_get_direct_pname):
(JSC::JIT::emitSlow_op_get_direct_pname):
(JSC::JIT::emit_op_get_structure_property_enumerator):
(JSC::JIT::emit_op_get_generic_property_enumerator):
(JSC::JIT::emit_op_next_enumerator_pname):
(JSC::JIT::emit_op_to_index_string):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_get_enumerable_length):
(JSC::JIT::emit_op_has_structure_property):
(JSC::JIT::emitSlow_op_has_structure_property):
(JSC::JIT::emit_op_has_generic_property):
(JSC::JIT::privateCompileHasIndexedProperty):
(JSC::JIT::emit_op_has_indexed_property):
(JSC::JIT::emitSlow_op_has_indexed_property):
(JSC::JIT::emit_op_get_direct_pname):
(JSC::JIT::emitSlow_op_get_direct_pname):
(JSC::JIT::emit_op_get_structure_property_enumerator):
(JSC::JIT::emit_op_get_generic_property_enumerator):
(JSC::JIT::emit_op_next_enumerator_pname):
(JSC::JIT::emit_op_to_index_string):

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitDoubleLoad):
(JSC::JIT::emitContiguousLoad):
(JSC::JIT::emitArrayStorageLoad):
(JSC::JIT::emitDoubleGetByVal): Deleted.
(JSC::JIT::emitContiguousGetByVal): Deleted.
(JSC::JIT::emitArrayStorageGetByVal): Deleted.

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emitContiguousLoad):
(JSC::JIT::emitDoubleLoad):
(JSC::JIT::emitArrayStorageLoad):
(JSC::JIT::emitContiguousGetByVal): Deleted.
(JSC::JIT::emitDoubleGetByVal): Deleted.
(JSC::JIT::emitArrayStorageGetByVal): Deleted.

  • llint/LowLevelInterpreter.asm:
  • parser/Nodes.h:
  • runtime/Arguments.cpp:

(JSC::Arguments::getOwnPropertyNames):

  • runtime/ClassInfo.h:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
  • runtime/EnumerationMode.h: Added.

(JSC::shouldIncludeDontEnumProperties):
(JSC::shouldExcludeDontEnumProperties):
(JSC::shouldIncludeJSObjectPropertyNames):
(JSC::modeThatSkipsJSObject):

  • runtime/JSActivation.cpp:

(JSC::JSActivation::getOwnNonIndexPropertyNames):

  • runtime/JSArray.cpp:

(JSC::JSArray::getOwnNonIndexPropertyNames):

  • runtime/JSArrayBuffer.cpp:

(JSC::JSArrayBuffer::getOwnNonIndexPropertyNames):

  • runtime/JSArrayBufferView.cpp:

(JSC::JSArrayBufferView::getOwnNonIndexPropertyNames):

  • runtime/JSCell.cpp:

(JSC::JSCell::getEnumerableLength):
(JSC::JSCell::getStructurePropertyNames):
(JSC::JSCell::getGenericPropertyNames):

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

(JSC::JSFunction::getOwnNonIndexPropertyNames):

  • runtime/JSGenericTypedArrayViewInlines.h:

(JSC::JSGenericTypedArrayView<Adaptor>::getOwnNonIndexPropertyNames):

  • runtime/JSObject.cpp:

(JSC::getClassPropertyNames):
(JSC::JSObject::hasOwnProperty):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::getOwnNonIndexPropertyNames):
(JSC::JSObject::getEnumerableLength):
(JSC::JSObject::getStructurePropertyNames):
(JSC::JSObject::getGenericPropertyNames):

  • runtime/JSObject.h:
  • runtime/JSPropertyNameEnumerator.cpp: Added.

(JSC::JSPropertyNameEnumerator::create):
(JSC::JSPropertyNameEnumerator::JSPropertyNameEnumerator):
(JSC::JSPropertyNameEnumerator::finishCreation):
(JSC::JSPropertyNameEnumerator::destroy):
(JSC::JSPropertyNameEnumerator::visitChildren):

  • runtime/JSPropertyNameEnumerator.h: Added.

(JSC::JSPropertyNameEnumerator::createStructure):
(JSC::JSPropertyNameEnumerator::propertyNameAtIndex):
(JSC::JSPropertyNameEnumerator::identifierSet):
(JSC::JSPropertyNameEnumerator::cachedPrototypeChain):
(JSC::JSPropertyNameEnumerator::setCachedPrototypeChain):
(JSC::JSPropertyNameEnumerator::cachedStructure):
(JSC::JSPropertyNameEnumerator::cachedStructureID):
(JSC::JSPropertyNameEnumerator::cachedInlineCapacity):
(JSC::JSPropertyNameEnumerator::cachedStructureIDOffset):
(JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
(JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset):
(JSC::JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset):
(JSC::structurePropertyNameEnumerator):
(JSC::genericPropertyNameEnumerator):

  • runtime/JSProxy.cpp:

(JSC::JSProxy::getEnumerableLength):
(JSC::JSProxy::getStructurePropertyNames):
(JSC::JSProxy::getGenericPropertyNames):

  • runtime/JSProxy.h:
  • runtime/JSSymbolTableObject.cpp:

(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):

  • runtime/PropertyNameArray.cpp:

(JSC::PropertyNameArray::add):
(JSC::PropertyNameArray::setPreviouslyEnumeratedProperties):

  • runtime/PropertyNameArray.h:

(JSC::RefCountedIdentifierSet::contains):
(JSC::RefCountedIdentifierSet::size):
(JSC::RefCountedIdentifierSet::add):
(JSC::PropertyNameArray::PropertyNameArray):
(JSC::PropertyNameArray::add):
(JSC::PropertyNameArray::addKnownUnique):
(JSC::PropertyNameArray::identifierSet):
(JSC::PropertyNameArray::canAddKnownUniqueForStructure):
(JSC::PropertyNameArray::setPreviouslyEnumeratedLength):

  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::getOwnNonIndexPropertyNames):
(JSC::RegExpObject::getPropertyNames):
(JSC::RegExpObject::getGenericPropertyNames):

  • runtime/RegExpObject.h:
  • runtime/StringObject.cpp:

(JSC::StringObject::getOwnPropertyNames):

  • runtime/Structure.cpp:

(JSC::Structure::getPropertyNamesFromStructure):
(JSC::Structure::setCachedStructurePropertyNameEnumerator):
(JSC::Structure::cachedStructurePropertyNameEnumerator):
(JSC::Structure::setCachedGenericPropertyNameEnumerator):
(JSC::Structure::cachedGenericPropertyNameEnumerator):
(JSC::Structure::canCacheStructurePropertyNameEnumerator):
(JSC::Structure::canCacheGenericPropertyNameEnumerator):
(JSC::Structure::canAccessPropertiesQuickly):

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

(JSC::StructureRareData::visitChildren):
(JSC::StructureRareData::cachedStructurePropertyNameEnumerator):
(JSC::StructureRareData::setCachedStructurePropertyNameEnumerator):
(JSC::StructureRareData::cachedGenericPropertyNameEnumerator):
(JSC::StructureRareData::setCachedGenericPropertyNameEnumerator):

  • runtime/StructureRareData.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Source/WebCore:
No new tests.

This patch splits for-in loops into three distinct parts:

  • Iterating over the indexed properties in the base object.
  • Iterating over the Structure properties in the base object.
  • Iterating over any other enumerable properties for that object and any objects in the prototype chain.


It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to
support the various operations required for each loop.

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::getEnumerableLength):
(WebCore::JSDOMWindow::getStructurePropertyNames):
(WebCore::JSDOMWindow::getGenericPropertyNames):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader):

  • bridge/runtime_array.cpp:

(JSC::RuntimeArray::getOwnPropertyNames):

Source/WebKit2:

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit::JSNPObject::invalidate): Fixed an invalid ASSERT that was crashing in debug builds.

Location:
branches/ftlopt/Source
Files:
12 added
71 edited

Legend:

Unmodified
Added
Removed
  • branches/ftlopt/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h

    r166493 r171605  
    517517                StringImpl* name = it->key.get();
    518518                StaticValueEntry* entry = it->value.get();
    519                 if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
     519                if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || shouldIncludeDontEnumProperties(mode)))
    520520                    propertyNames.add(Identifier(exec, name));
    521521            }
     
    528528                StringImpl* name = it->key.get();
    529529                StaticFunctionEntry* entry = it->value.get();
    530                 if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
     530                if (!(entry->attributes & kJSPropertyAttributeDontEnum) || shouldIncludeDontEnumProperties(mode))
    531531                    propertyNames.add(Identifier(exec, name));
    532532            }
  • branches/ftlopt/Source/JavaScriptCore/ChangeLog

    r171510 r171605  
     12014-07-23  Mark Hahnenberg  <[email protected]>
     2
     3        Refactor our current implementation of for-in
     4        https://bugs.webkit.org/show_bug.cgi?id=134142
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch splits for-in loops into three distinct parts:
     9
     10        - Iterating over the indexed properties in the base object.
     11        - Iterating over the Structure properties in the base object.
     12        - Iterating over any other enumerable properties for that object and any objects in the prototype chain.
     13 
     14        It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to
     15        support the various operations required for each loop.
     16
     17        * API/JSCallbackObjectFunctions.h:
     18        (JSC::JSCallbackObject<Parent>::getOwnNonIndexPropertyNames):
     19        * JavaScriptCore.xcodeproj/project.pbxproj:
     20        * bytecode/BytecodeList.json:
     21        * bytecode/BytecodeUseDef.h:
     22        (JSC::computeUsesForBytecodeOffset):
     23        (JSC::computeDefsForBytecodeOffset):
     24        * bytecode/CallLinkStatus.h:
     25        (JSC::CallLinkStatus::CallLinkStatus):
     26        * bytecode/CodeBlock.cpp:
     27        (JSC::CodeBlock::dumpBytecode):
     28        (JSC::CodeBlock::CodeBlock):
     29        * bytecompiler/BytecodeGenerator.cpp:
     30        (JSC::BytecodeGenerator::emitGetByVal):
     31        (JSC::BytecodeGenerator::emitComplexPopScopes):
     32        (JSC::BytecodeGenerator::emitGetEnumerableLength):
     33        (JSC::BytecodeGenerator::emitHasGenericProperty):
     34        (JSC::BytecodeGenerator::emitHasIndexedProperty):
     35        (JSC::BytecodeGenerator::emitHasStructureProperty):
     36        (JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator):
     37        (JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator):
     38        (JSC::BytecodeGenerator::emitNextEnumeratorPropertyName):
     39        (JSC::BytecodeGenerator::emitToIndexString):
     40        (JSC::BytecodeGenerator::pushIndexedForInScope):
     41        (JSC::BytecodeGenerator::popIndexedForInScope):
     42        (JSC::BytecodeGenerator::pushStructureForInScope):
     43        (JSC::BytecodeGenerator::popStructureForInScope):
     44        (JSC::BytecodeGenerator::invalidateForInContextForLocal):
     45        * bytecompiler/BytecodeGenerator.h:
     46        (JSC::ForInContext::ForInContext):
     47        (JSC::ForInContext::~ForInContext):
     48        (JSC::ForInContext::isValid):
     49        (JSC::ForInContext::invalidate):
     50        (JSC::ForInContext::local):
     51        (JSC::StructureForInContext::StructureForInContext):
     52        (JSC::StructureForInContext::type):
     53        (JSC::StructureForInContext::index):
     54        (JSC::StructureForInContext::property):
     55        (JSC::StructureForInContext::enumerator):
     56        (JSC::IndexedForInContext::IndexedForInContext):
     57        (JSC::IndexedForInContext::type):
     58        (JSC::IndexedForInContext::index):
     59        (JSC::BytecodeGenerator::pushOptimisedForIn): Deleted.
     60        (JSC::BytecodeGenerator::popOptimisedForIn): Deleted.
     61        * bytecompiler/NodesCodegen.cpp:
     62        (JSC::ReadModifyResolveNode::emitBytecode):
     63        (JSC::AssignResolveNode::emitBytecode):
     64        (JSC::ForInNode::tryGetBoundLocal):
     65        (JSC::ForInNode::emitLoopHeader):
     66        (JSC::ForInNode::emitMultiLoopBytecode):
     67        (JSC::ForInNode::emitBytecode):
     68        * debugger/DebuggerScope.h:
     69        * dfg/DFGAbstractHeap.h:
     70        * dfg/DFGAbstractInterpreterInlines.h:
     71        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     72        * dfg/DFGByteCodeParser.cpp:
     73        (JSC::DFG::ByteCodeParser::parseBlock):
     74        * dfg/DFGCapabilities.cpp:
     75        (JSC::DFG::capabilityLevel):
     76        * dfg/DFGClobberize.h:
     77        (JSC::DFG::clobberize):
     78        * dfg/DFGDoesGC.cpp:
     79        (JSC::DFG::doesGC):
     80        * dfg/DFGFixupPhase.cpp:
     81        (JSC::DFG::FixupPhase::fixupNode):
     82        * dfg/DFGHeapLocation.cpp:
     83        (WTF::printInternal):
     84        * dfg/DFGHeapLocation.h:
     85        * dfg/DFGNode.h:
     86        (JSC::DFG::Node::hasHeapPrediction):
     87        (JSC::DFG::Node::hasArrayMode):
     88        * dfg/DFGNodeType.h:
     89        * dfg/DFGPredictionPropagationPhase.cpp:
     90        (JSC::DFG::PredictionPropagationPhase::propagate):
     91        * dfg/DFGSafeToExecute.h:
     92        (JSC::DFG::safeToExecute):
     93        * dfg/DFGSpeculativeJIT.h:
     94        (JSC::DFG::SpeculativeJIT::callOperation):
     95        * dfg/DFGSpeculativeJIT32_64.cpp:
     96        (JSC::DFG::SpeculativeJIT::compile):
     97        * dfg/DFGSpeculativeJIT64.cpp:
     98        (JSC::DFG::SpeculativeJIT::compile):
     99        * jit/JIT.cpp:
     100        (JSC::JIT::privateCompileMainPass):
     101        (JSC::JIT::privateCompileSlowCases):
     102        * jit/JIT.h:
     103        (JSC::JIT::compileHasIndexedProperty):
     104        (JSC::JIT::emitInt32Load):
     105        * jit/JITInlines.h:
     106        (JSC::JIT::emitDoubleGetByVal):
     107        (JSC::JIT::emitLoadForArrayMode):
     108        (JSC::JIT::emitContiguousGetByVal):
     109        (JSC::JIT::emitArrayStorageGetByVal):
     110        * jit/JITOpcodes.cpp:
     111        (JSC::JIT::emit_op_get_enumerable_length):
     112        (JSC::JIT::emit_op_has_structure_property):
     113        (JSC::JIT::emitSlow_op_has_structure_property):
     114        (JSC::JIT::emit_op_has_generic_property):
     115        (JSC::JIT::privateCompileHasIndexedProperty):
     116        (JSC::JIT::emit_op_has_indexed_property):
     117        (JSC::JIT::emitSlow_op_has_indexed_property):
     118        (JSC::JIT::emit_op_get_direct_pname):
     119        (JSC::JIT::emitSlow_op_get_direct_pname):
     120        (JSC::JIT::emit_op_get_structure_property_enumerator):
     121        (JSC::JIT::emit_op_get_generic_property_enumerator):
     122        (JSC::JIT::emit_op_next_enumerator_pname):
     123        (JSC::JIT::emit_op_to_index_string):
     124        * jit/JITOpcodes32_64.cpp:
     125        (JSC::JIT::emit_op_get_enumerable_length):
     126        (JSC::JIT::emit_op_has_structure_property):
     127        (JSC::JIT::emitSlow_op_has_structure_property):
     128        (JSC::JIT::emit_op_has_generic_property):
     129        (JSC::JIT::privateCompileHasIndexedProperty):
     130        (JSC::JIT::emit_op_has_indexed_property):
     131        (JSC::JIT::emitSlow_op_has_indexed_property):
     132        (JSC::JIT::emit_op_get_direct_pname):
     133        (JSC::JIT::emitSlow_op_get_direct_pname):
     134        (JSC::JIT::emit_op_get_structure_property_enumerator):
     135        (JSC::JIT::emit_op_get_generic_property_enumerator):
     136        (JSC::JIT::emit_op_next_enumerator_pname):
     137        (JSC::JIT::emit_op_to_index_string):
     138        * jit/JITOperations.cpp:
     139        * jit/JITOperations.h:
     140        * jit/JITPropertyAccess.cpp:
     141        (JSC::JIT::emitDoubleLoad):
     142        (JSC::JIT::emitContiguousLoad):
     143        (JSC::JIT::emitArrayStorageLoad):
     144        (JSC::JIT::emitDoubleGetByVal): Deleted.
     145        (JSC::JIT::emitContiguousGetByVal): Deleted.
     146        (JSC::JIT::emitArrayStorageGetByVal): Deleted.
     147        * jit/JITPropertyAccess32_64.cpp:
     148        (JSC::JIT::emitContiguousLoad):
     149        (JSC::JIT::emitDoubleLoad):
     150        (JSC::JIT::emitArrayStorageLoad):
     151        (JSC::JIT::emitContiguousGetByVal): Deleted.
     152        (JSC::JIT::emitDoubleGetByVal): Deleted.
     153        (JSC::JIT::emitArrayStorageGetByVal): Deleted.
     154        * llint/LowLevelInterpreter.asm:
     155        * parser/Nodes.h:
     156        * runtime/Arguments.cpp:
     157        (JSC::Arguments::getOwnPropertyNames):
     158        * runtime/ClassInfo.h:
     159        * runtime/CommonSlowPaths.cpp:
     160        (JSC::SLOW_PATH_DECL):
     161        * runtime/CommonSlowPaths.h:
     162        * runtime/EnumerationMode.h: Added.
     163        (JSC::shouldIncludeDontEnumProperties):
     164        (JSC::shouldExcludeDontEnumProperties):
     165        (JSC::shouldIncludeJSObjectPropertyNames):
     166        (JSC::modeThatSkipsJSObject):
     167        * runtime/JSActivation.cpp:
     168        (JSC::JSActivation::getOwnNonIndexPropertyNames):
     169        * runtime/JSArray.cpp:
     170        (JSC::JSArray::getOwnNonIndexPropertyNames):
     171        * runtime/JSArrayBuffer.cpp:
     172        (JSC::JSArrayBuffer::getOwnNonIndexPropertyNames):
     173        * runtime/JSArrayBufferView.cpp:
     174        (JSC::JSArrayBufferView::getOwnNonIndexPropertyNames):
     175        * runtime/JSCell.cpp:
     176        (JSC::JSCell::getEnumerableLength):
     177        (JSC::JSCell::getStructurePropertyNames):
     178        (JSC::JSCell::getGenericPropertyNames):
     179        * runtime/JSCell.h:
     180        * runtime/JSFunction.cpp:
     181        (JSC::JSFunction::getOwnNonIndexPropertyNames):
     182        * runtime/JSGenericTypedArrayViewInlines.h:
     183        (JSC::JSGenericTypedArrayView<Adaptor>::getOwnNonIndexPropertyNames):
     184        * runtime/JSObject.cpp:
     185        (JSC::getClassPropertyNames):
     186        (JSC::JSObject::hasOwnProperty):
     187        (JSC::JSObject::getOwnPropertyNames):
     188        (JSC::JSObject::getOwnNonIndexPropertyNames):
     189        (JSC::JSObject::getEnumerableLength):
     190        (JSC::JSObject::getStructurePropertyNames):
     191        (JSC::JSObject::getGenericPropertyNames):
     192        * runtime/JSObject.h:
     193        * runtime/JSPropertyNameEnumerator.cpp: Added.
     194        (JSC::JSPropertyNameEnumerator::create):
     195        (JSC::JSPropertyNameEnumerator::JSPropertyNameEnumerator):
     196        (JSC::JSPropertyNameEnumerator::finishCreation):
     197        (JSC::JSPropertyNameEnumerator::destroy):
     198        (JSC::JSPropertyNameEnumerator::visitChildren):
     199        * runtime/JSPropertyNameEnumerator.h: Added.
     200        (JSC::JSPropertyNameEnumerator::createStructure):
     201        (JSC::JSPropertyNameEnumerator::propertyNameAtIndex):
     202        (JSC::JSPropertyNameEnumerator::identifierSet):
     203        (JSC::JSPropertyNameEnumerator::cachedPrototypeChain):
     204        (JSC::JSPropertyNameEnumerator::setCachedPrototypeChain):
     205        (JSC::JSPropertyNameEnumerator::cachedStructure):
     206        (JSC::JSPropertyNameEnumerator::cachedStructureID):
     207        (JSC::JSPropertyNameEnumerator::cachedInlineCapacity):
     208        (JSC::JSPropertyNameEnumerator::cachedStructureIDOffset):
     209        (JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
     210        (JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset):
     211        (JSC::JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset):
     212        (JSC::structurePropertyNameEnumerator):
     213        (JSC::genericPropertyNameEnumerator):
     214        * runtime/JSProxy.cpp:
     215        (JSC::JSProxy::getEnumerableLength):
     216        (JSC::JSProxy::getStructurePropertyNames):
     217        (JSC::JSProxy::getGenericPropertyNames):
     218        * runtime/JSProxy.h:
     219        * runtime/JSSymbolTableObject.cpp:
     220        (JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
     221        * runtime/PropertyNameArray.cpp:
     222        (JSC::PropertyNameArray::add):
     223        (JSC::PropertyNameArray::setPreviouslyEnumeratedProperties):
     224        * runtime/PropertyNameArray.h:
     225        (JSC::RefCountedIdentifierSet::contains):
     226        (JSC::RefCountedIdentifierSet::size):
     227        (JSC::RefCountedIdentifierSet::add):
     228        (JSC::PropertyNameArray::PropertyNameArray):
     229        (JSC::PropertyNameArray::add):
     230        (JSC::PropertyNameArray::addKnownUnique):
     231        (JSC::PropertyNameArray::identifierSet):
     232        (JSC::PropertyNameArray::canAddKnownUniqueForStructure):
     233        (JSC::PropertyNameArray::setPreviouslyEnumeratedLength):
     234        * runtime/RegExpObject.cpp:
     235        (JSC::RegExpObject::getOwnNonIndexPropertyNames):
     236        (JSC::RegExpObject::getPropertyNames):
     237        (JSC::RegExpObject::getGenericPropertyNames):
     238        * runtime/RegExpObject.h:
     239        * runtime/StringObject.cpp:
     240        (JSC::StringObject::getOwnPropertyNames):
     241        * runtime/Structure.cpp:
     242        (JSC::Structure::getPropertyNamesFromStructure):
     243        (JSC::Structure::setCachedStructurePropertyNameEnumerator):
     244        (JSC::Structure::cachedStructurePropertyNameEnumerator):
     245        (JSC::Structure::setCachedGenericPropertyNameEnumerator):
     246        (JSC::Structure::cachedGenericPropertyNameEnumerator):
     247        (JSC::Structure::canCacheStructurePropertyNameEnumerator):
     248        (JSC::Structure::canCacheGenericPropertyNameEnumerator):
     249        (JSC::Structure::canAccessPropertiesQuickly):
     250        * runtime/Structure.h:
     251        * runtime/StructureRareData.cpp:
     252        (JSC::StructureRareData::visitChildren):
     253        (JSC::StructureRareData::cachedStructurePropertyNameEnumerator):
     254        (JSC::StructureRareData::setCachedStructurePropertyNameEnumerator):
     255        (JSC::StructureRareData::cachedGenericPropertyNameEnumerator):
     256        (JSC::StructureRareData::setCachedGenericPropertyNameEnumerator):
     257        * runtime/StructureRareData.h:
     258        * runtime/VM.cpp:
     259        (JSC::VM::VM):
     260        * runtime/VM.h:
     261
    12622014-07-23  Saam Barati  <[email protected]>
    2263
  • branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r171510 r171605  
    816816                2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */; };
    817817                2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; };
     818                2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */; };
     819                2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */; };
    818820                2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */; };
    819821                2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
     
    839841                2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */; };
    840842                2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */; };
     843                2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
    841844                2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
    842845                2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */; };
     
    29702973                2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; };
    29712974                2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; };
     2975                2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameEnumerator.cpp; sourceTree = "<group>"; };
     2976                2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = "<group>"; };
    29722977                2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };
    29732978                2A343F7418A1748B0039B085 /* GCSegmentedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArray.h; sourceTree = "<group>"; };
     
    29942999                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = "<group>"; };
    29953000                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = "<group>"; };
     3001                2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = "<group>"; };
    29963002                2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; };
    29973003                2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = "<group>"; };
     
    49924998                                A7DCB77912E3D90500911940 /* WriteBarrier.h */,
    49934999                                C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
     5000                                2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */,
     5001                                2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */,
     5002                                2AD2EDFA19799E38004D6478 /* EnumerationMode.h */,
    49945003                        );
    49955004                        path = runtime;
     
    59585967                                A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
    59595968                                86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
     5969                                2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */,
    59605970                                52DAD38F195A164E00F30464 /* TypeLocation.h in Headers */,
    59615971                                52FB72151953760C00BB612E /* TypeSet.h in Headers */,
     
    66176627                                0FF729BC166AD360000F5BA3 /* ProfilerCompiledBytecode.h in Headers */,
    66186628                                0FF729BD166AD360000F5BA3 /* ProfilerDatabase.h in Headers */,
     6629                                2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */,
    66196630                                52B311011975B4670080857C /* TypeLocationCache.h in Headers */,
    66206631                                0FF729BE166AD360000F5BA3 /* ProfilerExecutionCounter.h in Headers */,
     
    77667777                                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
    77677778                                A7D89CFF17A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp in Sources */,
     7779                                2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */,
    77687780                                0FC20CB918556A3500C9E954 /* DFGSSALoweringPhase.cpp in Sources */,
    77697781                                0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
  • branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeList.json

    r170836 r171605  
    126126            { "name" : "op_profile_did_call", "length" : 2 },
    127127            { "name" : "op_end", "length" : 2 },
    128             { "name" : "op_profile_types_with_high_fidelity", "length" : 4 }
     128            { "name" : "op_profile_types_with_high_fidelity", "length" : 4 },
     129            { "name" : "op_get_enumerable_length", "length" : 3 },
     130            { "name" : "op_has_indexed_property", "length" : 5 },
     131            { "name" : "op_has_structure_property", "length" : 5 },
     132            { "name" : "op_has_generic_property", "length" : 4 },
     133            { "name" : "op_get_direct_pname", "length" : 7 },
     134            { "name" : "op_get_structure_property_enumerator", "length" : 4 },
     135            { "name" : "op_get_generic_property_enumerator", "length" : 5 },
     136            { "name" : "op_next_enumerator_pname", "length" : 4 },
     137            { "name" : "op_to_index_string", "length" : 3 }
    129138        ]
    130139    },
  • branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r170836 r171605  
    119119        return;
    120120    }
     121    case op_get_enumerable_length:
     122    case op_to_index_string:
    121123    case op_init_global_const_nop:
    122124    case op_init_global_const:
     
    151153        return;
    152154    }
     155    case op_has_generic_property:
     156    case op_get_structure_property_enumerator:
     157    case op_has_indexed_property:
     158    case op_next_enumerator_pname:
    153159    case op_get_by_val:
    154160    case op_get_argument_by_val:
     
    180186        return;
    181187    }
     188    case op_has_structure_property:
     189    case op_get_generic_property_enumerator:
    182190    case op_construct_varargs:
    183191    case op_call_varargs: {
     
    187195        return;
    188196    }
     197    case op_get_direct_pname:
    189198    case op_next_pname: {
    190199        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     
    299308        return;
    300309    // These all have a single destination for the first argument.
     310    case op_to_index_string:
     311    case op_get_generic_property_enumerator:
     312    case op_get_enumerable_length:
     313    case op_has_indexed_property:
     314    case op_has_structure_property:
     315    case op_has_generic_property:
     316    case op_get_direct_pname:
     317    case op_get_structure_property_enumerator:
     318    case op_next_enumerator_pname:
    301319    case op_next_pname:
    302320    case op_resolve_scope:
  • branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r171510 r171605  
    14001400            break;
    14011401        }
     1402        case op_get_enumerable_length: {
     1403            int dst = it[1].u.operand;
     1404            int base = it[2].u.operand;
     1405            printLocationAndOp(out, exec, location, it, "op_get_enumerable_length");
     1406            out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
     1407            it += OPCODE_LENGTH(op_get_enumerable_length) - 1;
     1408            break;
     1409        }
     1410        case op_has_indexed_property: {
     1411            int dst = it[1].u.operand;
     1412            int base = it[2].u.operand;
     1413            int propertyName = it[3].u.operand;
     1414            ArrayProfile* arrayProfile = it[4].u.arrayProfile;
     1415            printLocationAndOp(out, exec, location, it, "op_has_indexed_property");
     1416            out.printf("%s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), arrayProfile);
     1417            it += OPCODE_LENGTH(op_has_indexed_property) - 1;
     1418            break;
     1419        }
     1420        case op_has_structure_property: {
     1421            int dst = it[1].u.operand;
     1422            int base = it[2].u.operand;
     1423            int propertyName = it[3].u.operand;
     1424            int enumerator = it[4].u.operand;
     1425            printLocationAndOp(out, exec, location, it, "op_has_structure_property");
     1426            out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(enumerator).data());
     1427            it += OPCODE_LENGTH(op_has_structure_property) - 1;
     1428            break;
     1429        }
     1430        case op_has_generic_property: {
     1431            int dst = it[1].u.operand;
     1432            int base = it[2].u.operand;
     1433            int propertyName = it[3].u.operand;
     1434            printLocationAndOp(out, exec, location, it, "op_has_generic_property");
     1435            out.printf("%s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
     1436            it += OPCODE_LENGTH(op_has_generic_property) - 1;
     1437            break;
     1438        }
     1439        case op_get_direct_pname: {
     1440            int dst = it[1].u.operand;
     1441            int base = it[2].u.operand;
     1442            int propertyName = it[3].u.operand;
     1443            int index = it[4].u.operand;
     1444            int enumerator = it[5].u.operand;
     1445            ValueProfile* profile = it[6].u.profile;
     1446            printLocationAndOp(out, exec, location, it, "op_get_direct_pname");
     1447            out.printf("%s, %s, %s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(index).data(), registerName(enumerator).data(), profile);
     1448            it += OPCODE_LENGTH(op_get_direct_pname) - 1;
     1449            break;
     1450
     1451        }
     1452        case op_get_structure_property_enumerator: {
     1453            int dst = it[1].u.operand;
     1454            int base = it[2].u.operand;
     1455            printLocationAndOp(out, exec, location, it, "op_get_structure_property_enumerator");
     1456            out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
     1457            it += OPCODE_LENGTH(op_get_structure_property_enumerator) - 1;
     1458            break;
     1459        }
     1460        case op_get_generic_property_enumerator: {
     1461            int dst = it[1].u.operand;
     1462            int base = it[2].u.operand;
     1463            int length = it[3].u.operand;
     1464            int structureEnumerator = it[4].u.operand;
     1465            printLocationAndOp(out, exec, location, it, "op_get_generic_property_enumerator");
     1466            out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(length).data(), registerName(structureEnumerator).data());
     1467            it += OPCODE_LENGTH(op_get_generic_property_enumerator) - 1;
     1468            break;
     1469        }
     1470        case op_next_enumerator_pname: {
     1471            int dst = it[1].u.operand;
     1472            int enumerator = it[2].u.operand;
     1473            int index = it[3].u.operand;
     1474            printLocationAndOp(out, exec, location, it, "op_next_enumerator_pname");
     1475            out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
     1476            it += OPCODE_LENGTH(op_next_enumerator_pname) - 1;
     1477            break;
     1478        }
     1479        case op_to_index_string: {
     1480            int dst = it[1].u.operand;
     1481            int index = it[2].u.operand;
     1482            printLocationAndOp(out, exec, location, it, "op_to_index_string");
     1483            out.printf("%s, %s", registerName(dst).data(), registerName(index).data());
     1484            it += OPCODE_LENGTH(op_to_index_string) - 1;
     1485            break;
     1486        }
    14021487        case op_push_with_scope: {
    14031488            int r0 = (++it)->u.operand;
     
    18071892        }
    18081893        switch (pc[0].u.opcode) {
     1894        case op_has_indexed_property: {
     1895            int arrayProfileIndex = pc[opLength - 1].u.operand;
     1896            m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
     1897
     1898            instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
     1899            break;
     1900        }
    18091901        case op_call_varargs:
    18101902        case op_construct_varargs:
     
    18171909            FALLTHROUGH;
    18181910        }
     1911        case op_get_direct_pname:
    18191912        case op_get_by_id: {
    18201913            ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
  • branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r171510 r171605  
    14451445{
    14461446    for (size_t i = m_forInContextStack.size(); i > 0; i--) {
    1447         ForInContext& context = m_forInContextStack[i - 1];
    1448         if (context.propertyRegister == property) {
    1449             emitOpcode(op_get_by_pname);
    1450             instructions().append(dst->index());
    1451             instructions().append(base->index());
    1452             instructions().append(property->index());
    1453             instructions().append(context.expectedSubscriptRegister->index());
    1454             instructions().append(context.iterRegister->index());
    1455             instructions().append(context.indexRegister->index());
    1456             return dst;
    1457         }
    1458     }
     1447        ForInContext* context = m_forInContextStack[i - 1].get();
     1448        if (context->local() != property)
     1449            continue;
     1450
     1451        if (!context->isValid())
     1452            break;
     1453
     1454        if (context->type() == ForInContext::IndexedForInContextType) {
     1455            property = static_cast<IndexedForInContext*>(context)->index();
     1456            break;
     1457        }
     1458
     1459        ASSERT(context->type() == ForInContext::StructureForInContextType);
     1460        StructureForInContext* structureContext = static_cast<StructureForInContext*>(context);
     1461        UnlinkedValueProfile profile = emitProfiledOpcode(op_get_direct_pname);
     1462        instructions().append(kill(dst));
     1463        instructions().append(base->index());
     1464        instructions().append(property->index());
     1465        instructions().append(structureContext->index()->index());
     1466        instructions().append(structureContext->enumerator()->index());
     1467        instructions().append(profile);
     1468        return dst;
     1469    }
     1470
    14591471    UnlinkedArrayProfile arrayProfile = newArrayProfile();
    14601472    UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
     
    21702182        Vector<ControlFlowContext> savedScopeContextStack;
    21712183        Vector<SwitchInfo> savedSwitchContextStack;
    2172         Vector<ForInContext> savedForInContextStack;
     2184        Vector<std::unique_ptr<ForInContext>> savedForInContextStack;
    21732185        Vector<TryContext> poppedTryContexts;
    21742186        LabelScopeStore savedLabelScopes;
     
    21972209            }
    21982210            if (flipForIns) {
    2199                 savedForInContextStack = m_forInContextStack;
     2211                savedForInContextStack.swap(m_forInContextStack);
    22002212                m_forInContextStack.shrink(finallyContext.forInContextStackSize);
    22012213            }
     
    22372249                m_switchContextStack = savedSwitchContextStack;
    22382250            if (flipForIns)
    2239                 m_forInContextStack = savedForInContextStack;
     2251                m_forInContextStack.swap(savedForInContextStack);
    22402252            if (flipTries) {
    22412253                ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
     
    25702582}
    25712583
     2584RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
     2585{
     2586    emitOpcode(op_get_enumerable_length);
     2587    instructions().append(dst->index());
     2588    instructions().append(base->index());
     2589    return dst;
     2590}
     2591
     2592RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
     2593{
     2594    emitOpcode(op_has_generic_property);
     2595    instructions().append(dst->index());
     2596    instructions().append(base->index());
     2597    instructions().append(propertyName->index());
     2598    return dst;
     2599}
     2600
     2601RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
     2602{
     2603    UnlinkedArrayProfile arrayProfile = newArrayProfile();
     2604    emitOpcode(op_has_indexed_property);
     2605    instructions().append(dst->index());
     2606    instructions().append(base->index());
     2607    instructions().append(propertyName->index());
     2608    instructions().append(arrayProfile);
     2609    return dst;
     2610}
     2611
     2612RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
     2613{
     2614    emitOpcode(op_has_structure_property);
     2615    instructions().append(dst->index());
     2616    instructions().append(base->index());
     2617    instructions().append(propertyName->index());
     2618    instructions().append(enumerator->index());
     2619    return dst;
     2620}
     2621
     2622RegisterID* BytecodeGenerator::emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length)
     2623{
     2624    emitOpcode(op_get_structure_property_enumerator);
     2625    instructions().append(dst->index());
     2626    instructions().append(base->index());
     2627    instructions().append(length->index());
     2628    return dst;
     2629}
     2630
     2631RegisterID* BytecodeGenerator::emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator)
     2632{
     2633    emitOpcode(op_get_generic_property_enumerator);
     2634    instructions().append(dst->index());
     2635    instructions().append(base->index());
     2636    instructions().append(length->index());
     2637    instructions().append(structureEnumerator->index());
     2638    return dst;
     2639}
     2640
     2641RegisterID* BytecodeGenerator::emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
     2642{
     2643    emitOpcode(op_next_enumerator_pname);
     2644    instructions().append(dst->index());
     2645    instructions().append(enumerator->index());
     2646    instructions().append(index->index());
     2647    return dst;
     2648}
     2649
     2650RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
     2651{
     2652    emitOpcode(op_to_index_string);
     2653    instructions().append(dst->index());
     2654    instructions().append(index->index());
     2655    return dst;
     2656}
     2657
     2658void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
     2659{
     2660    if (!localRegister)
     2661        return;
     2662    m_forInContextStack.append(std::make_unique<IndexedForInContext>(localRegister, indexRegister));
     2663}
     2664
     2665void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
     2666{
     2667    if (!localRegister)
     2668        return;
     2669    m_forInContextStack.removeLast();
     2670}
     2671
     2672void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
     2673{
     2674    if (!localRegister)
     2675        return;
     2676    m_forInContextStack.append(std::make_unique<StructureForInContext>(localRegister, indexRegister, propertyRegister, enumeratorRegister));
     2677}
     2678
     2679void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
     2680{
     2681    if (!localRegister)
     2682        return;
     2683    m_forInContextStack.removeLast();
     2684}
     2685
     2686void BytecodeGenerator::invalidateForInContextForLocal(RegisterID* localRegister)
     2687{
     2688    // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
     2689    // either of the following conditions is true:
     2690    //
     2691    // (1) The loop iteration variable is re-assigned within the body of the loop.
     2692    // (2) The loop iteration variable is captured in the lexical scope of the function.
     2693    //
     2694    // These two situations occur sufficiently rarely that it's okay to use this style of
     2695    // "analysis" to make iteration faster. If we didn't want to do this, we would either have
     2696    // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
     2697    // reassigned, or we'd have to resort to runtime checks to see if the variable had been
     2698    // reassigned from its original value.
     2699    for (size_t i = m_forInContextStack.size(); i > 0; i--) {
     2700        ForInContext* context = m_forInContextStack[i - 1].get();
     2701        if (context->local() != localRegister)
     2702            continue;
     2703        context->invalidate();
     2704        break;
     2705    }
     2706}
     2707
    25722708} // namespace JSC
  • branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r171510 r171605  
    9898    };
    9999
    100     struct ForInContext {
    101         RefPtr<RegisterID> expectedSubscriptRegister;
    102         RefPtr<RegisterID> iterRegister;
    103         RefPtr<RegisterID> indexRegister;
    104         RefPtr<RegisterID> propertyRegister;
     100    class ForInContext {
     101    public:
     102        ForInContext(RegisterID* localRegister)
     103            : m_localRegister(localRegister)
     104            , m_isValid(true)
     105        {
     106        }
     107
     108        virtual ~ForInContext()
     109        {
     110        }
     111
     112        bool isValid() const { return m_isValid; }
     113        void invalidate() { m_isValid = false; }
     114
     115        enum ForInContextType {
     116            StructureForInContextType,
     117            IndexedForInContextType
     118        };
     119        virtual ForInContextType type() const = 0;
     120
     121        RegisterID* local() const { return m_localRegister.get(); }
     122
     123    private:
     124        RefPtr<RegisterID> m_localRegister;
     125        bool m_isValid;
     126    };
     127
     128    class StructureForInContext : public ForInContext {
     129    public:
     130        StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
     131            : ForInContext(localRegister)
     132            , m_indexRegister(indexRegister)
     133            , m_propertyRegister(propertyRegister)
     134            , m_enumeratorRegister(enumeratorRegister)
     135        {
     136        }
     137
     138        virtual ForInContextType type() const
     139        {
     140            return StructureForInContextType;
     141        }
     142
     143        RegisterID* index() const { return m_indexRegister.get(); }
     144        RegisterID* property() const { return m_propertyRegister.get(); }
     145        RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
     146
     147    private:
     148        RefPtr<RegisterID> m_indexRegister;
     149        RefPtr<RegisterID> m_propertyRegister;
     150        RefPtr<RegisterID> m_enumeratorRegister;
     151    };
     152
     153    class IndexedForInContext : public ForInContext {
     154    public:
     155        IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
     156            : ForInContext(localRegister)
     157            , m_indexRegister(indexRegister)
     158        {
     159        }
     160
     161        virtual ForInContextType type() const
     162        {
     163            return IndexedForInContextType;
     164        }
     165
     166        RegisterID* index() const { return m_indexRegister.get(); }
     167
     168    private:
     169        RefPtr<RegisterID> m_indexRegister;
    105170    };
    106171
     
    426491        RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
    427492
     493        RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
     494        RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
     495        RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
     496        RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
     497        RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
     498        RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
     499        RegisterID* emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
     500        RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
     501
    428502        void emitReadOnlyExceptionIfNeeded();
    429503
     
    455529        void popFinallyContext();
    456530
    457         void pushOptimisedForIn(RegisterID* expectedSubscript, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
    458         {
    459             ForInContext context = { expectedSubscript, iter, index, propertyRegister };
    460             m_forInContextStack.append(context);
    461         }
    462 
    463         void popOptimisedForIn()
    464         {
    465             m_forInContextStack.removeLast();
    466         }
     531        void pushIndexedForInScope(RegisterID* local, RegisterID* index);
     532        void popIndexedForInScope(RegisterID* local);
     533        void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
     534        void popStructureForInScope(RegisterID* local);
     535        void invalidateForInContextForLocal(RegisterID* local);
    467536
    468537        LabelScopePtr breakTarget(const Identifier&);
     
    663732        Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
    664733        Vector<SwitchInfo> m_switchContextStack;
    665         Vector<ForInContext> m_forInContextStack;
     734        Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
    666735        Vector<TryContext> m_tryContextStack;
    667736        Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
  • branches/ftlopt/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r170836 r171605  
    15061506            emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    15071507            generator.emitMove(local.get(), result.get());
     1508            generator.invalidateForInContextForLocal(local.get());
    15081509            if (generator.isProfilingTypesWithHighFidelity())
    15091510                generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     
    15121513       
    15131514        RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1515        generator.invalidateForInContextForLocal(local.get());
    15141516        return generator.moveToDestinationIfNeeded(dst, result);
    15151517    }
     
    15411543            generator.emitNode(tempDst.get(), m_right);
    15421544            generator.emitMove(local.get(), tempDst.get());
     1545            generator.invalidateForInContextForLocal(local.get());
    15431546            if (generator.isProfilingTypesWithHighFidelity())
    15441547                generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     
    15461549        }
    15471550        RegisterID* result = generator.emitNode(local.get(), m_right);
     1551        generator.invalidateForInContextForLocal(local.get());
    15481552        return generator.moveToDestinationIfNeeded(dst, result);
    15491553    }
     
    19211925// ------------------------------ ForInNode ------------------------------------
    19221926
    1923 void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1924 {
    1925     LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
    1926 
    1927     if (!m_lexpr->isAssignmentLocation()) {
    1928         emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
    1929         return;
    1930     }
    1931 
    1932     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
    1933 
    1934     RefPtr<RegisterID> base = generator.newTemporary();
    1935     generator.emitNode(base.get(), m_expr);
    1936     RefPtr<RegisterID> i = generator.newTemporary();
    1937     RefPtr<RegisterID> size = generator.newTemporary();
    1938     RefPtr<RegisterID> expectedSubscript;
    1939     RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
    1940     generator.emitJump(scope->continueTarget());
    1941 
    1942     RefPtr<Label> loopStart = generator.newLabel();
    1943     generator.emitLabel(loopStart.get());
    1944     generator.emitLoopHint();
    1945 
    1946     RegisterID* propertyName;
    1947     bool optimizedForinAccess = false;
     1927RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
     1928{
    19481929    if (m_lexpr->isResolveNode()) {
    19491930        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
    19501931        Local local = generator.local(ident);
    1951         if (!local.get()) {
    1952             propertyName = generator.newTemporary();
    1953             RefPtr<RegisterID> protect = propertyName;
     1932        if (local.isCaptured())
     1933            return nullptr;
     1934        return local.get();
     1935    }
     1936
     1937    if (m_lexpr->isDeconstructionNode()) {
     1938        DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
     1939        auto binding = assignNode->bindings();
     1940        if (!binding->isBindingNode())
     1941            return nullptr;
     1942
     1943        auto simpleBinding = static_cast<BindingNode*>(binding);
     1944        const Identifier& ident = simpleBinding->boundProperty();
     1945        Local local = generator.local(ident);
     1946        if (local.isCaptured())
     1947            return nullptr;
     1948        return local.get();
     1949    }
     1950
     1951    return nullptr;
     1952}
     1953
     1954void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
     1955{
     1956    if (m_lexpr->isResolveNode()) {
     1957        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
     1958        Local local = generator.local(ident);
     1959        if (local.get())
     1960            generator.emitMove(local.get(), propertyName);
     1961        else {
    19541962            if (generator.isStrictMode())
    19551963                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     
    19571965            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    19581966            generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
    1959         } else {
    1960             expectedSubscript = generator.newTemporary();
    1961             propertyName = expectedSubscript.get();
    1962             generator.emitMove(local.get(), propertyName);
    1963             generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), local.get());
    1964             optimizedForinAccess = true;
    1965         }
    1966     } else if (m_lexpr->isDotAccessorNode()) {
     1967        }
     1968        return;
     1969    }
     1970    if (m_lexpr->isDotAccessorNode()) {
    19671971        DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
    19681972        const Identifier& ident = assignNode->identifier();
    1969         propertyName = generator.newTemporary();
    1970         RefPtr<RegisterID> protect = propertyName;
    19711973        RegisterID* base = generator.emitNode(assignNode->base());
    1972 
    19731974        generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
    19741975        generator.emitPutById(base, ident, propertyName);
    1975     } else if (m_lexpr->isBracketAccessorNode()) {
     1976        return;
     1977    }
     1978    if (m_lexpr->isBracketAccessorNode()) {
    19761979        BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
    1977         propertyName = generator.newTemporary();
    1978         RefPtr<RegisterID> protect = propertyName;
    19791980        RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
    19801981        RegisterID* subscript = generator.emitNode(assignNode->subscript());
    1981        
    19821982        generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
    19831983        generator.emitPutByVal(base.get(), subscript, propertyName);
    1984     } else {
    1985         ASSERT(m_lexpr->isDeconstructionNode());
     1984        return;
     1985    }
     1986
     1987    if (m_lexpr->isDeconstructionNode()) {
    19861988        DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
    19871989        auto binding = assignNode->bindings();
    1988         if (binding->isBindingNode()) {
    1989             auto simpleBinding = static_cast<BindingNode*>(binding);
    1990             Identifier ident = simpleBinding->boundProperty();
    1991             Local local = generator.local(ident);
    1992             propertyName = local.get();
    1993             // FIXME: Should I emit expression info here?
    1994             if (!propertyName || local.isCaptured() || generator.isProfilingTypesWithHighFidelity())
    1995                 goto genericBinding;
    1996             expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
    1997             generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
    1998             optimizedForinAccess = true;
    1999             goto completedSimpleBinding;
    2000         } else {
    2001         genericBinding:
    2002             propertyName = generator.newTemporary();
    2003             RefPtr<RegisterID> protect(propertyName);
     1990        if (!binding->isBindingNode()) {
    20041991            assignNode->bindings()->bindValue(generator, propertyName);
    2005         }
    2006         completedSimpleBinding:
    2007         ;
    2008     }
    2009 
    2010     generator.emitNode(dst, m_statement);
    2011 
    2012     if (optimizedForinAccess)
    2013         generator.popOptimisedForIn();
    2014 
    2015     generator.emitLabel(scope->continueTarget());
    2016     generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
     1992            return;
     1993        }
     1994
     1995        auto simpleBinding = static_cast<BindingNode*>(binding);
     1996        const Identifier& ident = simpleBinding->boundProperty();
     1997        Local local = generator.local(ident);
     1998        if (!local.get() || local.isCaptured()) {
     1999            assignNode->bindings()->bindValue(generator, propertyName);
     2000            return;
     2001        }
     2002        generator.emitMove(local.get(), propertyName);
     2003        return;
     2004    }
     2005
     2006    RELEASE_ASSERT_NOT_REACHED();
     2007}
     2008
     2009void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
     2010{
     2011    if (!m_lexpr->isAssignmentLocation()) {
     2012        emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
     2013        return;
     2014    }
     2015
     2016    RefPtr<Label> end = generator.newLabel();
     2017
    20172018    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
    2018     generator.emitLabel(scope->breakTarget());
     2019
     2020    RefPtr<RegisterID> base = generator.newTemporary();
     2021    RefPtr<RegisterID> length;
     2022    RefPtr<RegisterID> structureEnumerator;
     2023    generator.emitNode(base.get(), m_expr);
     2024    RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
     2025
     2026    // Indexed property loop.
     2027    {
     2028        LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
     2029        RefPtr<Label> loopStart = generator.newLabel();
     2030        RefPtr<Label> loopEnd = generator.newLabel();
     2031
     2032        length = generator.emitGetEnumerableLength(generator.newTemporary(), base.get());
     2033        RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
     2034        RefPtr<RegisterID> propertyName = generator.newTemporary();
     2035
     2036        generator.emitLabel(loopStart.get());
     2037        generator.emitLoopHint();
     2038
     2039        RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
     2040        generator.emitJumpIfFalse(result.get(), loopEnd.get());
     2041        generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
     2042        generator.emitJumpIfFalse(result.get(), scope->continueTarget());
     2043
     2044        generator.emitToIndexString(propertyName.get(), i.get());
     2045        this->emitLoopHeader(generator, propertyName.get());
     2046
     2047        generator.pushIndexedForInScope(local.get(), i.get());
     2048        generator.emitNode(dst, m_statement);
     2049        generator.popIndexedForInScope(local.get());
     2050
     2051        generator.emitLabel(scope->continueTarget());
     2052        generator.emitInc(i.get());
     2053        generator.emitJump(loopStart.get());
     2054
     2055        generator.emitLabel(scope->breakTarget());
     2056        generator.emitJump(end.get());
     2057        generator.emitLabel(loopEnd.get());
     2058    }
     2059
     2060    // Structure property loop.
     2061    {
     2062        LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
     2063        RefPtr<Label> loopStart = generator.newLabel();
     2064        RefPtr<Label> loopEnd = generator.newLabel();
     2065
     2066        structureEnumerator = generator.emitGetStructurePropertyEnumerator(generator.newTemporary(), base.get(), length.get());
     2067        RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
     2068        RefPtr<RegisterID> propertyName = generator.newTemporary();
     2069        generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
     2070
     2071        generator.emitLabel(loopStart.get());
     2072        generator.emitLoopHint();
     2073
     2074        RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
     2075        generator.emitJumpIfTrue(result.get(), loopEnd.get());
     2076        generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), structureEnumerator.get());
     2077        generator.emitJumpIfFalse(result.get(), scope->continueTarget());
     2078
     2079        this->emitLoopHeader(generator, propertyName.get());
     2080
     2081        generator.pushStructureForInScope(local.get(), i.get(), propertyName.get(), structureEnumerator.get());
     2082        generator.emitNode(dst, m_statement);
     2083        generator.popStructureForInScope(local.get());
     2084
     2085        generator.emitLabel(scope->continueTarget());
     2086        generator.emitInc(i.get());
     2087        generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
     2088        generator.emitJump(loopStart.get());
     2089       
     2090        generator.emitLabel(scope->breakTarget());
     2091        generator.emitJump(end.get());
     2092        generator.emitLabel(loopEnd.get());
     2093    }
     2094
     2095    // Generic property loop.
     2096    {
     2097        LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
     2098        RefPtr<Label> loopStart = generator.newLabel();
     2099        RefPtr<Label> loopEnd = generator.newLabel();
     2100
     2101        RefPtr<RegisterID> genericEnumerator = generator.emitGetGenericPropertyEnumerator(generator.newTemporary(), base.get(), length.get(), structureEnumerator.get());
     2102        RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
     2103        RefPtr<RegisterID> propertyName = generator.newTemporary();
     2104
     2105        generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
     2106        RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
     2107        generator.emitJumpIfTrue(result.get(), loopEnd.get());
     2108
     2109        generator.emitLabel(loopStart.get());
     2110        generator.emitLoopHint();
     2111
     2112        this->emitLoopHeader(generator, propertyName.get());
     2113
     2114        generator.emitNode(dst, m_statement);
     2115
     2116        generator.emitLabel(scope->continueTarget());
     2117        generator.emitInc(i.get());
     2118        generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
     2119        generator.emitUnaryOp(op_eq_null, result.get(), propertyName.get());
     2120        generator.emitJumpIfTrue(result.get(), loopEnd.get());
     2121
     2122        generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
     2123        generator.emitJumpIfTrue(result.get(), loopStart.get());
     2124        generator.emitJump(scope->continueTarget());
     2125       
     2126        generator.emitLabel(scope->breakTarget());
     2127        generator.emitJump(end.get());
     2128        generator.emitLabel(loopEnd.get());
     2129    }
     2130
     2131    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
     2132    generator.emitLabel(end.get());
     2133}
     2134
     2135void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     2136{
     2137    this->emitMultiLoopBytecode(generator, dst);
    20192138}
    20202139
  • branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h

    r170680 r171605  
    9595    JSScope* jsScope() const { return m_scope.get(); }
    9696
    97     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
     97    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | OverridesVisitChildren | JSObject::StructureFlags;
    9898
    9999    WriteBarrier<JSScope> m_scope;
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractHeap.h

    r171106 r171605  
    5454    macro(JSObject_butterfly) \
    5555    macro(JSVariableObject_registers) \
     56    macro(JSPropertyNameEnumerator_cachedPropertyNames) \
    5657    macro(NamedProperties) \
    5758    macro(IndexedInt32Properties) \
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r171495 r171605  
    17781778    }
    17791779       
    1780     case In:
     1780    case In: {
    17811781        // FIXME: We can determine when the property definitely exists based on abstract
    17821782        // value information.
     
    17841784        forNode(node).setType(SpecBoolean);
    17851785        break;
    1786            
     1786    }
     1787           
     1788    case GetEnumerableLength: {
     1789        forNode(node).setType(SpecInt32);
     1790        break;
     1791    }
     1792    case HasGenericProperty: {
     1793        forNode(node).setType(SpecBoolean);
     1794        break;
     1795    }
     1796    case HasStructureProperty: {
     1797        forNode(node).setType(SpecBoolean);
     1798        break;
     1799    }
     1800    case HasIndexedProperty: {
     1801        ArrayMode mode = node->arrayMode();
     1802        switch (mode.type()) {
     1803        case Array::Int32:
     1804        case Array::Double:
     1805        case Array::Contiguous:
     1806        case Array::ArrayStorage: {
     1807            break;
     1808        }
     1809        default: {
     1810            clobberWorld(node->origin.semantic, clobberLimit);
     1811            break;
     1812        }
     1813        }
     1814        forNode(node).setType(SpecBoolean);
     1815        break;
     1816    }
     1817    case GetDirectPname: {
     1818        clobberWorld(node->origin.semantic, clobberLimit);
     1819        forNode(node).makeHeapTop();
     1820        break;
     1821    }
     1822    case GetStructurePropertyEnumerator: {
     1823        forNode(node).setType(SpecCell);
     1824        break;
     1825    }
     1826    case GetGenericPropertyEnumerator: {
     1827        forNode(node).setType(SpecCell);
     1828        break;
     1829    }
     1830    case GetEnumeratorPname: {
     1831        forNode(node).setType(SpecString | SpecOther);
     1832        break;
     1833    }
     1834    case ToIndexString: {
     1835        forNode(node).setType(SpecString);
     1836        break;
     1837    }
     1838
    17871839    case GetGlobalVar:
    17881840        forNode(node).makeHeapTop();
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r171389 r171605  
    31823182        }
    31833183
     3184        case op_get_enumerable_length: {
     3185            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumerableLength,
     3186                get(VirtualRegister(currentInstruction[2].u.operand))));
     3187            NEXT_OPCODE(op_get_enumerable_length);
     3188        }
     3189
     3190        case op_has_generic_property: {
     3191            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(HasGenericProperty,
     3192                get(VirtualRegister(currentInstruction[2].u.operand)),
     3193                get(VirtualRegister(currentInstruction[3].u.operand))));
     3194            NEXT_OPCODE(op_has_generic_property);
     3195        }
     3196
     3197        case op_has_structure_property: {
     3198            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(HasStructureProperty,
     3199                get(VirtualRegister(currentInstruction[2].u.operand)),
     3200                get(VirtualRegister(currentInstruction[3].u.operand)),
     3201                get(VirtualRegister(currentInstruction[4].u.operand))));
     3202            NEXT_OPCODE(op_has_structure_property);
     3203        }
     3204
     3205        case op_has_indexed_property: {
     3206            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
     3207            ArrayMode arrayMode = getArrayModeConsideringSlowPath(currentInstruction[4].u.arrayProfile, Array::Read);
     3208            Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
     3209            Node* hasIterableProperty = addToGraph(HasIndexedProperty, OpInfo(arrayMode.asWord()), base, property);
     3210            set(VirtualRegister(currentInstruction[1].u.operand), hasIterableProperty);
     3211            NEXT_OPCODE(op_has_indexed_property);
     3212        }
     3213
     3214        case op_get_direct_pname: {
     3215            SpeculatedType prediction = getPredictionWithoutOSRExit();
     3216           
     3217            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
     3218            Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
     3219            Node* index = get(VirtualRegister(currentInstruction[4].u.operand));
     3220            Node* enumerator = get(VirtualRegister(currentInstruction[5].u.operand));
     3221
     3222            addVarArgChild(base);
     3223            addVarArgChild(property);
     3224            addVarArgChild(index);
     3225            addVarArgChild(enumerator);
     3226            set(VirtualRegister(currentInstruction[1].u.operand),
     3227                addToGraph(Node::VarArg, GetDirectPname, OpInfo(0), OpInfo(prediction)));
     3228
     3229            NEXT_OPCODE(op_get_direct_pname);
     3230        }
     3231
     3232        case op_get_structure_property_enumerator: {
     3233            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetStructurePropertyEnumerator,
     3234                get(VirtualRegister(currentInstruction[2].u.operand)),
     3235                get(VirtualRegister(currentInstruction[3].u.operand))));
     3236            NEXT_OPCODE(op_get_structure_property_enumerator);
     3237        }
     3238
     3239        case op_get_generic_property_enumerator: {
     3240            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetGenericPropertyEnumerator,
     3241                get(VirtualRegister(currentInstruction[2].u.operand)),
     3242                get(VirtualRegister(currentInstruction[3].u.operand)),
     3243                get(VirtualRegister(currentInstruction[4].u.operand))));
     3244            NEXT_OPCODE(op_get_generic_property_enumerator);
     3245        }
     3246
     3247        case op_next_enumerator_pname: {
     3248            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorPname,
     3249                get(VirtualRegister(currentInstruction[2].u.operand)),
     3250                get(VirtualRegister(currentInstruction[3].u.operand))));
     3251            NEXT_OPCODE(op_next_enumerator_pname);
     3252        }
     3253
     3254        case op_to_index_string: {
     3255            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToIndexString,
     3256                get(VirtualRegister(currentInstruction[2].u.operand))));
     3257            NEXT_OPCODE(op_to_index_string);
     3258        }
     3259
    31843260        default:
    31853261            // Parse failed! This should not happen because the capabilities checker
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r170571 r171605  
    194194    case op_in:
    195195    case op_get_from_scope:
     196    case op_get_enumerable_length:
     197    case op_has_generic_property:
     198    case op_has_structure_property:
     199    case op_has_indexed_property:
     200    case op_get_direct_pname:
     201    case op_get_structure_property_enumerator:
     202    case op_get_generic_property_enumerator:
     203    case op_next_enumerator_pname:
     204    case op_to_index_string:
    196205        return CanCompileAndInline;
    197206
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGClobberize.h

    r171106 r171605  
    146146        return;
    147147       
     148    case HasGenericProperty:
     149    case HasStructureProperty:
     150    case GetEnumerableLength:
     151    case GetStructurePropertyEnumerator:
     152    case GetGenericPropertyEnumerator: {
     153        read(World);
     154        write(SideState);
     155        return;
     156    }
     157
     158    case GetDirectPname: {
     159        // This reads and writes world because it can end up calling a generic getByVal
     160        // if the Structure changed, which could in turn end up calling a getter.
     161        read(World);
     162        write(World);
     163        return;
     164    }
     165
     166    case ToIndexString:
     167    case GetEnumeratorPname: {
     168        def(PureValue(node));
     169        return;
     170    }
     171
     172    case HasIndexedProperty: {
     173        read(JSObject_butterfly);
     174        ArrayMode mode = node->arrayMode();
     175        switch (mode.type()) {
     176        case Array::Int32: {
     177            if (mode.isInBounds()) {
     178                read(Butterfly_publicLength);
     179                read(IndexedInt32Properties);
     180                def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
     181                return;
     182            }
     183            read(World);
     184            return;
     185        }
     186           
     187        case Array::Double: {
     188            if (mode.isInBounds()) {
     189                read(Butterfly_publicLength);
     190                read(IndexedDoubleProperties);
     191                def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
     192                return;
     193            }
     194            read(World);
     195            return;
     196        }
     197           
     198        case Array::Contiguous: {
     199            if (mode.isInBounds()) {
     200                read(Butterfly_publicLength);
     201                read(IndexedContiguousProperties);
     202                def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
     203                return;
     204            }
     205            read(World);
     206            return;
     207        }
     208
     209        case Array::ArrayStorage: {
     210            if (mode.isInBounds()) {
     211                read(Butterfly_vectorLength);
     212                read(IndexedArrayStorageProperties);
     213                return;
     214            }
     215            read(World);
     216            return;
     217        }
     218
     219        default: {
     220            read(World);
     221            write(World);
     222            return;
     223        }
     224        }
     225        RELEASE_ASSERT_NOT_REACHED();
     226        return;
     227    }
     228
    148229    case ArithAdd:
    149230    case ArithSub:
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r170092 r171605  
    188188    case GetGetterSetterByOffset:
    189189    case PutByOffset:
     190    case GetEnumerableLength:
     191    case HasGenericProperty:
     192    case HasStructureProperty:
     193    case HasIndexedProperty:
     194    case GetDirectPname:
    190195        return false;
    191196
     
    210215    case NewTypedArray:
    211216    case ThrowReferenceError:
     217    case GetStructurePropertyEnumerator:
     218    case GetGenericPropertyEnumerator:
     219    case GetEnumeratorPname:
     220    case ToIndexString:
    212221        return true;
    213222       
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r171389 r171605  
    10351035            }
    10361036            break;
     1037
     1038        case GetEnumerableLength: {
     1039            fixEdge<CellUse>(node->child1());
     1040            break;
     1041        }
     1042        case HasGenericProperty: {
     1043            fixEdge<StringUse>(node->child2());
     1044            break;
     1045        }
     1046        case HasStructureProperty: {
     1047            fixEdge<StringUse>(node->child2());
     1048            fixEdge<KnownCellUse>(node->child3());
     1049            break;
     1050        }
     1051        case HasIndexedProperty: {
     1052            node->setArrayMode(
     1053                node->arrayMode().refine(
     1054                    m_graph, node,
     1055                    node->child1()->prediction(),
     1056                    node->child2()->prediction(),
     1057                    SpecNone, node->flags()));
     1058           
     1059            blessArrayOperation(node->child1(), node->child2(), node->child3());
     1060            fixEdge<CellUse>(node->child1());
     1061            fixEdge<KnownInt32Use>(node->child2());
     1062            break;
     1063        }
     1064        case GetDirectPname: {
     1065            Edge& base = m_graph.varArgChild(node, 0);
     1066            Edge& property = m_graph.varArgChild(node, 1);
     1067            Edge& index = m_graph.varArgChild(node, 2);
     1068            Edge& enumerator = m_graph.varArgChild(node, 3);
     1069            fixEdge<CellUse>(base);
     1070            fixEdge<KnownCellUse>(property);
     1071            fixEdge<KnownInt32Use>(index);
     1072            fixEdge<KnownCellUse>(enumerator);
     1073            break;
     1074        }
     1075        case GetStructurePropertyEnumerator: {
     1076            fixEdge<CellUse>(node->child1());
     1077            fixEdge<KnownInt32Use>(node->child2());
     1078            break;
     1079        }
     1080        case GetGenericPropertyEnumerator: {
     1081            fixEdge<CellUse>(node->child1());
     1082            fixEdge<KnownInt32Use>(node->child2());
     1083            fixEdge<KnownCellUse>(node->child3());
     1084            break;
     1085        }
     1086        case GetEnumeratorPname: {
     1087            fixEdge<KnownCellUse>(node->child1());
     1088            fixEdge<KnownInt32Use>(node->child2());
     1089            break;
     1090        }
     1091        case ToIndexString: {
     1092            fixEdge<KnownInt32Use>(node->child1());
     1093            break;
     1094        }
    10371095           
    10381096#if !ASSERT_DISABLED
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r171106 r171605  
    109109        return;
    110110       
     111    case HasIndexedPropertyLoc:
     112        out.print("HasIndexedPorpertyLoc");
     113        return;
     114       
    111115    case IndexedPropertyLoc:
    112116        out.print("IndexedPorpertyLoc");
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.h

    r171106 r171605  
    4545    GetterLoc,
    4646    GlobalVariableLoc,
     47    HasIndexedPropertyLoc,
    4748    IndexedPropertyLoc,
    4849    IndexedPropertyStorageLoc,
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h

    r171152 r171605  
    10021002    {
    10031003        switch (op()) {
     1004        case GetDirectPname:
    10041005        case GetById:
    10051006        case GetByIdFlush:
     
    12621263        case ArrayPush:
    12631264        case ArrayPop:
     1265        case HasIndexedProperty:
    12641266            return true;
    12651267        default:
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h

    r171495 r171605  
    289289    macro(StoreBarrier, NodeMustGenerate) \
    290290    macro(StoreBarrierWithNullCheck, NodeMustGenerate) \
     291    \
     292    /* For-in enumeration opcodes */\
     293    macro(GetEnumerableLength, NodeMustGenerate | NodeResultJS) \
     294    macro(HasIndexedProperty, NodeResultBoolean) \
     295    macro(HasStructureProperty, NodeResultBoolean) \
     296    macro(HasGenericProperty, NodeResultBoolean) \
     297    macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \
     298    macro(GetStructurePropertyEnumerator, NodeMustGenerate | NodeResultJS) \
     299    macro(GetGenericPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
     300    macro(GetEnumeratorPname, NodeMustGenerate | NodeResultJS) \
     301    macro(ToIndexString, NodeResultJS)
    291302
    292303// This enum generates a monotonically increasing id for all Node types,
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r170092 r171605  
    181181        case GetByOffset:
    182182        case MultiGetByOffset:
     183        case GetDirectPname:
    183184        case Call:
    184185        case Construct:
     
    550551            changed |= setPrediction(SpecBoolean);
    551552            break;
     553
     554        case GetEnumerableLength: {
     555            changed |= setPrediction(SpecInt32);
     556            break;
     557        }
     558        case HasGenericProperty: {
     559            changed |= setPrediction(SpecBoolean);
     560            break;
     561        }
     562        case HasStructureProperty: {
     563            changed |= setPrediction(SpecBoolean);
     564            break;
     565        }
     566        case HasIndexedProperty: {
     567            changed |= setPrediction(SpecBoolean);
     568            break;
     569        }
     570        case GetStructurePropertyEnumerator: {
     571            changed |= setPrediction(SpecCell);
     572            break;
     573        }
     574        case GetGenericPropertyEnumerator: {
     575            changed |= setPrediction(SpecCell);
     576            break;
     577        }
     578        case GetEnumeratorPname: {
     579            changed |= setPrediction(SpecCell | SpecOther);
     580            break;
     581        }
     582        case ToIndexString: {
     583            changed |= setPrediction(SpecString);
     584            break;
     585        }
    552586
    553587#ifndef NDEBUG
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r171389 r171605  
    256256    case GetGetter:
    257257    case GetSetter:
     258    case GetEnumerableLength:
     259    case HasGenericProperty:
     260    case HasStructureProperty:
     261    case HasIndexedProperty:
     262    case GetDirectPname:
     263    case GetStructurePropertyEnumerator:
     264    case GetGenericPropertyEnumerator:
     265    case GetEnumeratorPname:
     266    case ToIndexString:
    258267        return true;
    259268
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r171389 r171605  
    10351035        return appendCallWithExceptionCheckSetResult(operation, result);
    10361036    }
     1037    JITCompiler::Call callOperation(C_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     1038    {
     1039        m_jit.setupArgumentsWithExecState(arg1, arg2);
     1040        return appendCallWithExceptionCheckSetResult(operation, result);
     1041    }
     1042    JITCompiler::Call callOperation(C_JITOperation_ECZC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     1043    {
     1044        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
     1045        return appendCallWithExceptionCheckSetResult(operation, result);
     1046    }
    10371047    JITCompiler::Call callOperation(C_JITOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
    10381048    {
     
    11321142        m_jit.setupArgumentsExecState();
    11331143        return appendCallWithCallFrameRollbackOnExceptionSetResult(operation, result);
     1144    }
     1145    JITCompiler::Call callOperation(Z_JITOperation_EC operation, GPRReg result, GPRReg arg1)
     1146    {
     1147        m_jit.setupArgumentsWithExecState(arg1);
     1148        return appendCallWithExceptionCheckSetResult(operation, result);
    11341149    }
    11351150
     
    12491264        return appendCallWithExceptionCheckSetResult(operation, result);
    12501265    }
     1266    JITCompiler::Call callOperation(J_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     1267    {
     1268        m_jit.setupArgumentsWithExecState(arg1, arg2);
     1269        return appendCallWithExceptionCheckSetResult(operation, result);
     1270    }
    12511271    JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo, GPRReg arg1, const StringImpl* uid)
    12521272    {
     
    12601280    }
    12611281    JITCompiler::Call callOperation(J_JITOperation_EDA operation, GPRReg result, FPRReg arg1, GPRReg arg2)
     1282    {
     1283        m_jit.setupArgumentsWithExecState(arg1, arg2);
     1284        return appendCallWithExceptionCheckSetResult(operation, result);
     1285    }
     1286    JITCompiler::Call callOperation(J_JITOperation_EJC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     1287    {
     1288        m_jit.setupArgumentsWithExecState(arg1, arg2);
     1289        return appendCallWithExceptionCheckSetResult(operation, result);
     1290    }
     1291    JITCompiler::Call callOperation(J_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
    12621292    {
    12631293        m_jit.setupArgumentsWithExecState(arg1, arg2);
     
    13101340    {
    13111341        m_jit.setupArgumentsWithExecState(arg1);
     1342        return appendCallWithExceptionCheckSetResult(operation, result);
     1343    }
     1344    JITCompiler::Call callOperation(C_JITOperation_EJJC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     1345    {
     1346        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
     1347        return appendCallWithExceptionCheckSetResult(operation, result);
     1348    }
     1349    JITCompiler::Call callOperation(C_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     1350    {
     1351        m_jit.setupArgumentsWithExecState(arg1, arg2);
     1352        return appendCallWithExceptionCheckSetResult(operation, result);
     1353    }
     1354    JITCompiler::Call callOperation(C_JITOperation_EJZC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     1355    {
     1356        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
    13121357        return appendCallWithExceptionCheckSetResult(operation, result);
    13131358    }
     
    14851530        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
    14861531    }
     1532    JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg resultPayload, GPRReg resultTag, GPRReg arg1)
     1533    {
     1534        m_jit.setupArgumentsWithExecState(arg1);
     1535        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1536    }
     1537    JITCompiler::Call callOperation(J_JITOperation_EJC operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
     1538    {
     1539        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2);
     1540        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1541    }
    14871542    JITCompiler::Call callOperation(J_JITOperation_EJssZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
    14881543    {
     
    15141569    {
    15151570        m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
     1571        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1572    }
     1573    JITCompiler::Call callOperation(J_JITOperation_ECZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
     1574    {
     1575        m_jit.setupArgumentsWithExecState(arg1, arg2);
    15161576        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
    15171577    }
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r171495 r171605  
    3838#include "GetterSetter.h"
    3939#include "JSActivation.h"
     40#include "JSPropertyNameEnumerator.h"
    4041#include "ObjectPrototype.h"
    4142#include "JSCInlines.h"
     
    45494550    }
    45504551
     4552    case GetEnumerableLength: {
     4553        SpeculateCellOperand base(this, node->child1());
     4554        GPRResult result(this);
     4555        GPRReg resultGPR = result.gpr();
     4556
     4557        flushRegisters();
     4558        callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
     4559        int32Result(resultGPR, node);
     4560        break;
     4561    }
     4562    case HasGenericProperty: {
     4563        JSValueOperand base(this, node->child1());
     4564        SpeculateCellOperand property(this, node->child2());
     4565        GPRResult resultPayload(this);
     4566        GPRResult2 resultTag(this);
     4567        GPRReg basePayloadGPR = base.payloadGPR();
     4568        GPRReg baseTagGPR = base.tagGPR();
     4569        GPRReg resultPayloadGPR = resultPayload.gpr();
     4570        GPRReg resultTagGPR = resultTag.gpr();
     4571
     4572        flushRegisters();
     4573        callOperation(operationHasGenericProperty, resultTagGPR, resultPayloadGPR, baseTagGPR, basePayloadGPR, property.gpr());
     4574        booleanResult(resultPayloadGPR, node);
     4575        break;
     4576    }
     4577    case HasStructureProperty: {
     4578        JSValueOperand base(this, node->child1());
     4579        SpeculateCellOperand property(this, node->child2());
     4580        SpeculateCellOperand enumerator(this, node->child3());
     4581        GPRTemporary scratch(this);
     4582        GPRResult resultPayload(this);
     4583        GPRResult2 resultTag(this);
     4584
     4585        GPRReg baseTagGPR = base.tagGPR();
     4586        GPRReg basePayloadGPR = base.payloadGPR();
     4587        GPRReg propertyGPR = property.gpr();
     4588        GPRReg scratchGPR = scratch.gpr();
     4589        GPRReg resultPayloadGPR = resultPayload.gpr();
     4590        GPRReg resultTagGPR = resultTag.gpr();
     4591
     4592        m_jit.load32(MacroAssembler::Address(basePayloadGPR, JSCell::structureIDOffset()), scratchGPR);
     4593        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual,
     4594            scratchGPR,
     4595            MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset()));
     4596
     4597        moveTrueTo(resultPayloadGPR);
     4598        MacroAssembler::Jump done = m_jit.jump();
     4599
     4600        done.link(&m_jit);
     4601
     4602        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultTagGPR, resultPayloadGPR, baseTagGPR, basePayloadGPR, propertyGPR));
     4603        booleanResult(resultPayloadGPR, node);
     4604        break;
     4605    }
     4606    case HasIndexedProperty: {
     4607        SpeculateCellOperand base(this, node->child1());
     4608        SpeculateInt32Operand index(this, node->child2());
     4609        GPRResult resultPayload(this);
     4610        GPRResult2 resultTag(this);
     4611
     4612        GPRReg baseGPR = base.gpr();
     4613        GPRReg indexGPR = index.gpr();
     4614        GPRReg resultPayloadGPR = resultPayload.gpr();
     4615        GPRReg resultTagGPR = resultTag.gpr();
     4616
     4617        MacroAssembler::JumpList slowCases;
     4618        ArrayMode mode = node->arrayMode();
     4619        switch (mode.type()) {
     4620        case Array::Int32:
     4621        case Array::Contiguous: {
     4622            ASSERT(!!node->child3());
     4623            StorageOperand storage(this, node->child3());
     4624            GPRTemporary scratch(this);
     4625           
     4626            GPRReg storageGPR = storage.gpr();
     4627            GPRReg scratchGPR = scratch.gpr();
     4628
     4629            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())));
     4630            m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
     4631            slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
     4632            break;
     4633        }
     4634        case Array::Double: {
     4635            ASSERT(!!node->child3());
     4636            StorageOperand storage(this, node->child3());
     4637            FPRTemporary scratch(this);
     4638            FPRReg scratchFPR = scratch.fpr();
     4639            GPRReg storageGPR = storage.gpr();
     4640
     4641            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())));
     4642            m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
     4643            slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
     4644            break;
     4645        }
     4646        case Array::ArrayStorage: {
     4647            ASSERT(!!node->child3());
     4648            StorageOperand storage(this, node->child3());
     4649            GPRTemporary scratch(this);
     4650
     4651            GPRReg storageGPR = storage.gpr();
     4652            GPRReg scratchGPR = scratch.gpr();
     4653
     4654            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
     4655            m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
     4656            slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
     4657            break;
     4658        }
     4659        default: {
     4660            slowCases.append(m_jit.jump());
     4661            break;
     4662        }
     4663        }
     4664
     4665        moveTrueTo(resultPayloadGPR);
     4666        MacroAssembler::Jump done = m_jit.jump();
     4667
     4668        addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedProperty, resultTagGPR, resultPayloadGPR, baseGPR, indexGPR));
     4669       
     4670        done.link(&m_jit);
     4671        booleanResult(resultPayloadGPR, node);
     4672        break;
     4673    }
     4674    case GetDirectPname: {
     4675        Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
     4676        Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
     4677        Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
     4678        Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);
     4679
     4680        SpeculateCellOperand base(this, baseEdge);
     4681        SpeculateCellOperand property(this, propertyEdge);
     4682        SpeculateInt32Operand index(this, indexEdge);
     4683        SpeculateCellOperand enumerator(this, enumeratorEdge);
     4684        GPRResult resultPayload(this);
     4685        GPRResult2 resultTag(this);
     4686        GPRTemporary scratch(this);
     4687
     4688        GPRReg baseGPR = base.gpr();
     4689        GPRReg propertyGPR = property.gpr();
     4690        GPRReg indexGPR = index.gpr();
     4691        GPRReg enumeratorGPR = enumerator.gpr();
     4692        GPRReg resultTagGPR = resultTag.gpr();
     4693        GPRReg resultPayloadGPR = resultPayload.gpr();
     4694        GPRReg scratchGPR = scratch.gpr();
     4695
     4696        // Check the structure
     4697        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
     4698        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual,
     4699            scratchGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
     4700       
     4701        // Compute the offset
     4702        // If index is less than the enumerator's cached inline storage, then it's an inline access
     4703        MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
     4704            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     4705
     4706        m_jit.move(indexGPR, scratchGPR);
     4707        m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
     4708        m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagGPR);
     4709        m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadGPR);
     4710
     4711        MacroAssembler::Jump done = m_jit.jump();
     4712       
     4713        // Otherwise it's out of line
     4714        outOfLineAccess.link(&m_jit);
     4715        m_jit.move(indexGPR, scratchGPR);
     4716        m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
     4717        m_jit.neg32(scratchGPR);
     4718        m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
     4719        // We use resultPayloadGPR as a temporary here. We have to make sure clobber it after getting the
     4720        // value out of indexGPR and enumeratorGPR because resultPayloadGPR could reuse either of those registers.
     4721        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultPayloadGPR);
     4722        int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
     4723        m_jit.load32(MacroAssembler::BaseIndex(resultPayloadGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagGPR);
     4724        m_jit.load32(MacroAssembler::BaseIndex(resultPayloadGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadGPR);
     4725
     4726        done.link(&m_jit);
     4727
     4728        m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), scratchGPR);
     4729        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationGetByValCell, resultTagGPR, resultPayloadGPR, baseGPR, scratchGPR, propertyGPR));
     4730
     4731        jsValueResult(resultTagGPR, resultPayloadGPR, node);
     4732        break;
     4733    }
     4734    case GetStructurePropertyEnumerator: {
     4735        SpeculateCellOperand base(this, node->child1());
     4736        SpeculateInt32Operand length(this, node->child2());
     4737        GPRResult result(this);
     4738        GPRReg resultGPR = result.gpr();
     4739
     4740        flushRegisters();
     4741        callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
     4742        cellResult(resultGPR, node);
     4743        break;
     4744    }
     4745    case GetGenericPropertyEnumerator: {
     4746        SpeculateCellOperand base(this, node->child1());
     4747        SpeculateInt32Operand length(this, node->child2());
     4748        SpeculateCellOperand enumerator(this, node->child3());
     4749        GPRResult result(this);
     4750        GPRReg resultGPR = result.gpr();
     4751
     4752        flushRegisters();
     4753        callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
     4754        cellResult(resultGPR, node);
     4755        break;
     4756    }
     4757    case GetEnumeratorPname: {
     4758        SpeculateCellOperand enumerator(this, node->child1());
     4759        SpeculateInt32Operand index(this, node->child2());
     4760        GPRTemporary scratch(this);
     4761        GPRResult resultPayload(this);
     4762        GPRResult2 resultTag(this);
     4763
     4764        GPRReg enumeratorGPR = enumerator.gpr();
     4765        GPRReg indexGPR = index.gpr();
     4766        GPRReg scratchGPR = scratch.gpr();
     4767        GPRReg resultTagGPR = resultTag.gpr();
     4768        GPRReg resultPayloadGPR = resultPayload.gpr();
     4769
     4770        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below,
     4771            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
     4772
     4773        m_jit.move(MacroAssembler::TrustedImm32(JSValue::NullTag), resultTagGPR);
     4774        m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
     4775
     4776        MacroAssembler::Jump done = m_jit.jump();
     4777        inBounds.link(&m_jit);
     4778
     4779        m_jit.loadPtr(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), scratchGPR);
     4780        m_jit.loadPtr(MacroAssembler::BaseIndex(scratchGPR, indexGPR, MacroAssembler::ScalePtr), resultPayloadGPR);
     4781        m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), resultTagGPR);
     4782
     4783        done.link(&m_jit);
     4784        jsValueResult(resultTagGPR, resultPayloadGPR, node);
     4785        break;
     4786    }
     4787    case ToIndexString: {
     4788        SpeculateInt32Operand index(this, node->child1());
     4789        GPRResult result(this);
     4790        GPRReg resultGPR = result.gpr();
     4791
     4792        flushRegisters();
     4793        callOperation(operationToIndexString, resultGPR, index.gpr());
     4794        cellResult(resultGPR, node);
     4795        break;
     4796    }
     4797
    45514798    case ForceOSRExit: {
    45524799        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
  • branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r171495 r171605  
    3838#include "GetterSetter.h"
    3939#include "JSCInlines.h"
     40#include "JSPropertyNameEnumerator.h"
    4041#include "ObjectPrototype.h"
    4142#include "SpillRegistersMode.h"
     
    45844585    }
    45854586
     4587    case GetEnumerableLength: {
     4588        SpeculateCellOperand base(this, node->child1());
     4589        GPRResult result(this);
     4590        GPRReg resultGPR = result.gpr();
     4591
     4592        flushRegisters();
     4593        callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
     4594        int32Result(resultGPR, node);
     4595        break;
     4596    }
     4597    case HasGenericProperty: {
     4598        JSValueOperand base(this, node->child1());
     4599        SpeculateCellOperand property(this, node->child2());
     4600        GPRResult result(this);
     4601        GPRReg resultGPR = result.gpr();
     4602
     4603        flushRegisters();
     4604        callOperation(operationHasGenericProperty, resultGPR, base.gpr(), property.gpr());
     4605        jsValueResult(resultGPR, node, DataFormatJSBoolean);
     4606        break;
     4607    }
     4608    case HasStructureProperty: {
     4609        JSValueOperand base(this, node->child1());
     4610        SpeculateCellOperand property(this, node->child2());
     4611        SpeculateCellOperand enumerator(this, node->child3());
     4612        GPRTemporary scratch(this);
     4613        GPRResult result(this);
     4614
     4615        GPRReg baseGPR = base.gpr();
     4616        GPRReg propertyGPR = property.gpr();
     4617        GPRReg scratchGPR = scratch.gpr();
     4618        GPRReg resultGPR = result.gpr();
     4619
     4620        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
     4621        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual,
     4622            scratchGPR,
     4623            MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset()));
     4624
     4625        moveTrueTo(resultGPR);
     4626        MacroAssembler::Jump done = m_jit.jump();
     4627
     4628        done.link(&m_jit);
     4629
     4630        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultGPR, baseGPR, propertyGPR));
     4631        jsValueResult(resultGPR, node, DataFormatJSBoolean);
     4632        break;
     4633    }
     4634    case HasIndexedProperty: {
     4635        SpeculateCellOperand base(this, node->child1());
     4636        SpeculateInt32Operand index(this, node->child2());
     4637        GPRResult result(this);
     4638
     4639        GPRReg baseGPR = base.gpr();
     4640        GPRReg indexGPR = index.gpr();
     4641        GPRReg resultGPR = result.gpr();
     4642
     4643        MacroAssembler::JumpList slowCases;
     4644        ArrayMode mode = node->arrayMode();
     4645        switch (mode.type()) {
     4646        case Array::Int32:
     4647        case Array::Contiguous: {
     4648            ASSERT(!!node->child3());
     4649            StorageOperand storage(this, node->child3());
     4650            GPRTemporary scratch(this);
     4651           
     4652            GPRReg storageGPR = storage.gpr();
     4653            GPRReg scratchGPR = scratch.gpr();
     4654
     4655            MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
     4656            if (mode.isInBounds())
     4657                speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
     4658            else
     4659                slowCases.append(outOfBounds);
     4660
     4661            m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchGPR);
     4662            slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
     4663            moveTrueTo(resultGPR);
     4664            break;
     4665        }
     4666        case Array::Double: {
     4667            ASSERT(!!node->child3());
     4668            StorageOperand storage(this, node->child3());
     4669            FPRTemporary scratch(this);
     4670            FPRReg scratchFPR = scratch.fpr();
     4671            GPRReg storageGPR = storage.gpr();
     4672
     4673            MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
     4674            if (mode.isInBounds())
     4675                speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
     4676            else
     4677                slowCases.append(outOfBounds);
     4678
     4679            m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
     4680            slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
     4681            break;
     4682        }
     4683        case Array::ArrayStorage: {
     4684            ASSERT(!!node->child3());
     4685            StorageOperand storage(this, node->child3());
     4686            GPRTemporary scratch(this);
     4687
     4688            GPRReg storageGPR = storage.gpr();
     4689            GPRReg scratchGPR = scratch.gpr();
     4690
     4691            MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
     4692            if (mode.isInBounds())
     4693                speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
     4694            else   
     4695                slowCases.append(outOfBounds);
     4696
     4697            m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), scratchGPR);
     4698            slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
     4699            moveTrueTo(resultGPR);
     4700            break;
     4701        }
     4702        default: {
     4703            slowCases.append(m_jit.jump());
     4704            break;
     4705        }
     4706        }
     4707
     4708        addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedProperty, resultGPR, baseGPR, indexGPR));
     4709       
     4710        jsValueResult(resultGPR, node, DataFormatJSBoolean);
     4711        break;
     4712    }
     4713    case GetDirectPname: {
     4714        Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
     4715        Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
     4716        Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
     4717        Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);
     4718
     4719        SpeculateCellOperand base(this, baseEdge);
     4720        SpeculateCellOperand property(this, propertyEdge);
     4721        SpeculateInt32Operand index(this, indexEdge);
     4722        SpeculateCellOperand enumerator(this, enumeratorEdge);
     4723        GPRResult result(this);
     4724        GPRTemporary scratch1(this);
     4725        GPRTemporary scratch2(this);
     4726
     4727        GPRReg baseGPR = base.gpr();
     4728        GPRReg propertyGPR = property.gpr();
     4729        GPRReg indexGPR = index.gpr();
     4730        GPRReg enumeratorGPR = enumerator.gpr();
     4731        GPRReg resultGPR = result.gpr();
     4732        GPRReg scratch1GPR = scratch1.gpr();
     4733        GPRReg scratch2GPR = scratch2.gpr();
     4734
     4735        // Check the structure
     4736        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratch1GPR);
     4737        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual,
     4738            scratch1GPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
     4739       
     4740        // Compute the offset
     4741        // If index is less than the enumerator's cached inline storage, then it's an inline access
     4742        MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
     4743            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     4744
     4745        m_jit.load64(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultGPR);
     4746
     4747        MacroAssembler::Jump done = m_jit.jump();
     4748       
     4749        // Otherwise it's out of line
     4750        outOfLineAccess.link(&m_jit);
     4751        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratch2GPR);
     4752        m_jit.move(indexGPR, scratch1GPR);
     4753        m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratch1GPR);
     4754        m_jit.neg32(scratch1GPR);
     4755        m_jit.signExtend32ToPtr(scratch1GPR, scratch1GPR);
     4756        int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
     4757        m_jit.load64(MacroAssembler::BaseIndex(scratch2GPR, scratch1GPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultGPR);
     4758
     4759        done.link(&m_jit);
     4760
     4761        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationGetByVal, resultGPR, baseGPR, propertyGPR));
     4762
     4763        jsValueResult(resultGPR, node);
     4764        break;
     4765    }
     4766    case GetStructurePropertyEnumerator: {
     4767        SpeculateCellOperand base(this, node->child1());
     4768        SpeculateInt32Operand length(this, node->child2());
     4769        GPRResult result(this);
     4770        GPRReg resultGPR = result.gpr();
     4771
     4772        flushRegisters();
     4773        callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
     4774        cellResult(resultGPR, node);
     4775        break;
     4776    }
     4777    case GetGenericPropertyEnumerator: {
     4778        SpeculateCellOperand base(this, node->child1());
     4779        SpeculateInt32Operand length(this, node->child2());
     4780        SpeculateCellOperand enumerator(this, node->child3());
     4781        GPRResult result(this);
     4782        GPRReg resultGPR = result.gpr();
     4783
     4784        flushRegisters();
     4785        callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
     4786        cellResult(resultGPR, node);
     4787        break;
     4788    }
     4789    case GetEnumeratorPname: {
     4790        SpeculateCellOperand enumerator(this, node->child1());
     4791        SpeculateInt32Operand index(this, node->child2());
     4792        GPRTemporary scratch1(this);
     4793        GPRTemporary scratch2(this);
     4794        GPRResult result(this);
     4795
     4796        GPRReg enumeratorGPR = enumerator.gpr();
     4797        GPRReg indexGPR = index.gpr();
     4798        GPRReg scratch1GPR = scratch1.gpr();
     4799        GPRReg scratch2GPR = scratch2.gpr();
     4800        GPRReg resultGPR = result.gpr();
     4801
     4802        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below,
     4803            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
     4804
     4805        m_jit.move(MacroAssembler::TrustedImm32(ValueNull), resultGPR);
     4806
     4807        MacroAssembler::Jump done = m_jit.jump();
     4808        inBounds.link(&m_jit);
     4809
     4810        m_jit.loadPtr(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), scratch1GPR);
     4811        m_jit.move(indexGPR, scratch2GPR);
     4812        m_jit.signExtend32ToPtr(scratch2GPR, scratch2GPR);
     4813        m_jit.load64(MacroAssembler::BaseIndex(scratch1GPR, scratch2GPR, MacroAssembler::TimesEight), resultGPR);
     4814
     4815        done.link(&m_jit);
     4816        jsValueResult(resultGPR, node);
     4817        break;
     4818    }
     4819    case ToIndexString: {
     4820        SpeculateInt32Operand index(this, node->child1());
     4821        GPRResult result(this);
     4822        GPRReg resultGPR = result.gpr();
     4823
     4824        flushRegisters();
     4825        callOperation(operationToIndexString, resultGPR, index.gpr());
     4826        cellResult(resultGPR, node);
     4827        break;
     4828    }
     4829
    45864830#if ENABLE(FTL_JIT)       
    45874831    case CheckTierUpInLoop: {
  • branches/ftlopt/Source/JavaScriptCore/jit/JIT.cpp

    r169143 r171605  
    304304        DEFINE_OP(op_get_from_scope)
    305305        DEFINE_OP(op_put_to_scope)
     306
     307        DEFINE_OP(op_get_enumerable_length)
     308        DEFINE_OP(op_has_generic_property)
     309        DEFINE_OP(op_has_structure_property)
     310        DEFINE_OP(op_has_indexed_property)
     311        DEFINE_OP(op_get_direct_pname)
     312        DEFINE_OP(op_get_structure_property_enumerator)
     313        DEFINE_OP(op_get_generic_property_enumerator)
     314        DEFINE_OP(op_next_enumerator_pname)
     315        DEFINE_OP(op_to_index_string)
    306316        default:
    307317            RELEASE_ASSERT_NOT_REACHED();
     
    421431        DEFINE_SLOWCASE_OP(op_to_number)
    422432        DEFINE_SLOWCASE_OP(op_to_primitive)
     433        DEFINE_SLOWCASE_OP(op_has_indexed_property)
     434        DEFINE_SLOWCASE_OP(op_has_structure_property)
     435        DEFINE_SLOWCASE_OP(op_get_direct_pname)
    423436
    424437        DEFINE_SLOWCASE_OP(op_resolve_scope)
  • branches/ftlopt/Source/JavaScriptCore/jit/JIT.h

    r171389 r171605  
    221221        }
    222222
     223        static void compileHasIndexedProperty(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
     224        {
     225            JIT jit(vm, codeBlock);
     226            jit.m_bytecodeOffset = byValInfo->bytecodeIndex;
     227            jit.privateCompileHasIndexedProperty(byValInfo, returnAddress, arrayMode);
     228        }
     229
    223230        static CodeRef compileCTINativeCall(VM* vm, NativeFunction func)
    224231        {
     
    247254        void privateCompileGetByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode);
    248255        void privateCompilePutByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode);
     256
     257        void privateCompileHasIndexedProperty(ByValInfo*, ReturnAddressPtr, JITArrayMode);
    249258
    250259        Label privateCompileCTINativeCall(VM*, bool isConstruct = false);
     
    328337        // Structure is already profiled. Returns the slow cases. Fall-through
    329338        // case contains result in regT0, and it is not yet profiled.
     339        JumpList emitInt32Load(Instruction* instruction, PatchableJump& badType) { return emitContiguousLoad(instruction, badType, Int32Shape); }
     340        JumpList emitDoubleLoad(Instruction*, PatchableJump& badType);
     341        JumpList emitContiguousLoad(Instruction*, PatchableJump& badType, IndexingType expectedShape = ContiguousShape);
     342        JumpList emitArrayStorageLoad(Instruction*, PatchableJump& badType);
     343        JumpList emitLoadForArrayMode(Instruction*, JITArrayMode, PatchableJump& badType);
     344
    330345        JumpList emitInt32GetByVal(Instruction* instruction, PatchableJump& badType) { return emitContiguousGetByVal(instruction, badType, Int32Shape); }
    331346        JumpList emitDoubleGetByVal(Instruction*, PatchableJump& badType);
     
    541556        void emit_op_unsigned(Instruction*);
    542557        void emit_op_urshift(Instruction*);
     558        void emit_op_get_enumerable_length(Instruction*);
     559        void emit_op_has_generic_property(Instruction*);
     560        void emit_op_has_structure_property(Instruction*);
     561        void emit_op_has_indexed_property(Instruction*);
     562        void emit_op_get_direct_pname(Instruction*);
     563        void emit_op_get_structure_property_enumerator(Instruction*);
     564        void emit_op_get_generic_property_enumerator(Instruction*);
     565        void emit_op_next_enumerator_pname(Instruction*);
     566        void emit_op_to_index_string(Instruction*);
    543567
    544568        void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
     
    594618        void emitSlow_op_unsigned(Instruction*, Vector<SlowCaseEntry>::iterator&);
    595619        void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
     620        void emitSlow_op_has_indexed_property(Instruction*, Vector<SlowCaseEntry>::iterator&);
     621        void emitSlow_op_has_structure_property(Instruction*, Vector<SlowCaseEntry>::iterator&);
     622        void emitSlow_op_get_direct_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
    596623
    597624        void emit_op_resolve_scope(Instruction*);
  • branches/ftlopt/Source/JavaScriptCore/jit/JITInlines.h

    r167329 r171605  
    3333namespace JSC {
    3434
     35#if USE(JSVALUE64)
     36inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump& badType)
     37{
     38    JumpList slowCases = emitDoubleLoad(instruction, badType);
     39    moveDoubleTo64(fpRegT0, regT0);
     40    sub64(tagTypeNumberRegister, regT0);
     41    return slowCases;
     42}
     43#else
     44inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump& badType)
     45{
     46    JumpList slowCases = emitDoubleLoad(instruction, badType);
     47    moveDoubleToInts(fpRegT0, regT0, regT1);
     48    return slowCases;
     49}
     50#endif // USE(JSVALUE64)
     51
     52ALWAYS_INLINE MacroAssembler::JumpList JIT::emitLoadForArrayMode(Instruction* currentInstruction, JITArrayMode arrayMode, PatchableJump& badType)
     53{
     54    switch (arrayMode) {
     55    case JITInt32:
     56        return emitInt32Load(currentInstruction, badType);
     57    case JITDouble:
     58        return emitDoubleLoad(currentInstruction, badType);
     59    case JITContiguous:
     60        return emitContiguousLoad(currentInstruction, badType);
     61    case JITArrayStorage:
     62        return emitArrayStorageLoad(currentInstruction, badType);
     63    default:
     64        RELEASE_ASSERT_NOT_REACHED();
     65        break;
     66    }
     67}
     68
     69inline MacroAssembler::JumpList JIT::emitContiguousGetByVal(Instruction* instruction, PatchableJump& badType, IndexingType expectedShape)
     70{
     71    return emitContiguousLoad(instruction, badType, expectedShape);
     72}
     73
     74inline MacroAssembler::JumpList JIT::emitArrayStorageGetByVal(Instruction* instruction, PatchableJump& badType)
     75{
     76    return emitArrayStorageLoad(instruction, badType);
     77}
     78
    3579ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(int src)
    3680{
  • branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r168443 r171605  
    3737#include "JSCell.h"
    3838#include "JSFunction.h"
     39#include "JSPropertyNameEnumerator.h"
    3940#include "JSPropertyNameIterator.h"
    4041#include "LinkBuffer.h"
    4142#include "MaxFrameExtentForSlowPathCall.h"
     43#include "RepatchBuffer.h"
    4244#include "SlowPathCall.h"
    4345#include "VirtualRegister.h"
     
    12111213}
    12121214
     1215#if USE(JSVALUE64)
     1216void JIT::emit_op_get_enumerable_length(Instruction* currentInstruction)
     1217{
     1218    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_enumerable_length);
     1219    slowPathCall.call();
     1220}
     1221
     1222void JIT::emit_op_has_structure_property(Instruction* currentInstruction)
     1223{
     1224    int dst = currentInstruction[1].u.operand;
     1225    int base = currentInstruction[2].u.operand;
     1226    int enumerator = currentInstruction[4].u.operand;
     1227
     1228    emitGetVirtualRegister(base, regT0);
     1229    emitGetVirtualRegister(enumerator, regT1);
     1230    emitJumpSlowCaseIfNotJSCell(regT0, base);
     1231
     1232    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
     1233    addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
     1234   
     1235    move(TrustedImm32(ValueTrue), regT0);
     1236    emitPutVirtualRegister(dst);
     1237}
     1238
     1239void JIT::emitSlow_op_has_structure_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1240{
     1241    linkSlowCase(iter);
     1242    linkSlowCase(iter);
     1243
     1244    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_structure_property);
     1245    slowPathCall.call();
     1246}
     1247
     1248void JIT::emit_op_has_generic_property(Instruction* currentInstruction)
     1249{
     1250    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_generic_property);
     1251    slowPathCall.call();
     1252}
     1253
     1254void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
     1255{
     1256    Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex;
     1257   
     1258    PatchableJump badType;
     1259   
     1260    // FIXME: Add support for other types like TypedArrays and Arguments.
     1261    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
     1262    JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType);
     1263    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
     1264    Jump done = jump();
     1265
     1266    LinkBuffer patchBuffer(*m_vm, this, m_codeBlock);
     1267   
     1268    patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
     1269    patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
     1270   
     1271    patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
     1272   
     1273    byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
     1274        m_codeBlock, patchBuffer,
     1275        ("Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.value()));
     1276   
     1277    RepatchBuffer repatchBuffer(m_codeBlock);
     1278    repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code()));
     1279    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationHasIndexedPropertyGeneric));
     1280}
     1281
     1282void JIT::emit_op_has_indexed_property(Instruction* currentInstruction)
     1283{
     1284    int dst = currentInstruction[1].u.operand;
     1285    int base = currentInstruction[2].u.operand;
     1286    int property = currentInstruction[3].u.operand;
     1287    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1288   
     1289    emitGetVirtualRegisters(base, regT0, property, regT1);
     1290
     1291    // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
     1292    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
     1293    // number was signed since m_vectorLength is always less than intmax (since the total allocation
     1294    // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
     1295    // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
     1296    // extending since it makes it easier to re-tag the value in the slow case.
     1297    zeroExtend32ToPtr(regT1, regT1);
     1298
     1299    emitJumpSlowCaseIfNotJSCell(regT0, base);
     1300    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
     1301    and32(TrustedImm32(IndexingShapeMask), regT2);
     1302
     1303    JITArrayMode mode = chooseArrayMode(profile);
     1304    PatchableJump badType;
     1305
     1306    // FIXME: Add support for other types like TypedArrays and Arguments.
     1307    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
     1308    JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType);
     1309   
     1310    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
     1311
     1312    addSlowCase(badType);
     1313    addSlowCase(slowCases);
     1314   
     1315    Label done = label();
     1316   
     1317    emitPutVirtualRegister(dst);
     1318   
     1319    m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     1320}
     1321
     1322void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1323{
     1324    int dst = currentInstruction[1].u.operand;
     1325    int base = currentInstruction[2].u.operand;
     1326    int property = currentInstruction[3].u.operand;
     1327    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1328   
     1329    linkSlowCaseIfNotJSCell(iter, base); // base cell check
     1330    linkSlowCase(iter); // base array check
     1331   
     1332    Jump skipProfiling = jump();
     1333   
     1334    linkSlowCase(iter); // vector length check
     1335    linkSlowCase(iter); // empty value
     1336   
     1337    emitArrayProfileOutOfBoundsSpecialCase(profile);
     1338   
     1339    skipProfiling.link(this);
     1340   
     1341    Label slowPath = label();
     1342   
     1343    emitGetVirtualRegister(base, regT0);
     1344    emitGetVirtualRegister(property, regT1);
     1345    Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT0, regT1);
     1346
     1347    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
     1348    m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
     1349    m_byValInstructionIndex++;
     1350}
     1351
     1352void JIT::emit_op_get_direct_pname(Instruction* currentInstruction)
     1353{
     1354    int dst = currentInstruction[1].u.operand;
     1355    int base = currentInstruction[2].u.operand;
     1356    int index = currentInstruction[4].u.operand;
     1357    int enumerator = currentInstruction[5].u.operand;
     1358
     1359    // Check that base is a cell
     1360    emitGetVirtualRegister(base, regT0);
     1361    emitJumpSlowCaseIfNotJSCell(regT0, base);
     1362
     1363    // Check the structure
     1364    emitGetVirtualRegister(enumerator, regT2);
     1365    load32(Address(regT0, JSCell::structureIDOffset()), regT1);
     1366    addSlowCase(branch32(NotEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedStructureIDOffset())));
     1367
     1368    // Compute the offset
     1369    emitGetVirtualRegister(index, regT1);
     1370    // If index is less than the enumerator's cached inline storage, then it's an inline access
     1371    Jump outOfLineAccess = branch32(AboveOrEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     1372    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
     1373    signExtend32ToPtr(regT1, regT1);
     1374    load64(BaseIndex(regT0, regT1, TimesEight), regT0);
     1375   
     1376    Jump done = jump();
     1377
     1378    // Otherwise it's out of line
     1379    outOfLineAccess.link(this);
     1380    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
     1381    sub32(Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT1);
     1382    neg32(regT1);
     1383    signExtend32ToPtr(regT1, regT1);
     1384    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
     1385    load64(BaseIndex(regT0, regT1, TimesEight, offsetOfFirstProperty), regT0);
     1386   
     1387    done.link(this);
     1388    emitValueProfilingSite();
     1389    emitPutVirtualRegister(dst, regT0);
     1390}
     1391
     1392void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1393{
     1394    int base = currentInstruction[2].u.operand;
     1395    linkSlowCaseIfNotJSCell(iter, base);
     1396    linkSlowCase(iter);
     1397
     1398    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
     1399    slowPathCall.call();
     1400}
     1401
     1402void JIT::emit_op_get_structure_property_enumerator(Instruction* currentInstruction)
     1403{
     1404    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_structure_property_enumerator);
     1405    slowPathCall.call();
     1406}
     1407
     1408void JIT::emit_op_get_generic_property_enumerator(Instruction* currentInstruction)
     1409{
     1410    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_generic_property_enumerator);
     1411    slowPathCall.call();
     1412}
     1413
     1414void JIT::emit_op_next_enumerator_pname(Instruction* currentInstruction)
     1415{
     1416    int dst = currentInstruction[1].u.operand;
     1417    int enumerator = currentInstruction[2].u.operand;
     1418    int index = currentInstruction[3].u.operand;
     1419
     1420    emitGetVirtualRegister(index, regT0);
     1421    emitGetVirtualRegister(enumerator, regT1);
     1422    Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
     1423
     1424    move(TrustedImm32(ValueNull), regT0);
     1425
     1426    Jump done = jump();
     1427    inBounds.link(this);
     1428
     1429    loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
     1430    signExtend32ToPtr(regT0, regT0);
     1431    load64(BaseIndex(regT1, regT0, TimesEight), regT0);
     1432
     1433    done.link(this);
     1434    emitPutVirtualRegister(dst);
     1435}
     1436
     1437void JIT::emit_op_to_index_string(Instruction* currentInstruction)
     1438{
     1439    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_index_string);
     1440    slowPathCall.call();
     1441}
     1442#endif // USE(JSVALUE64)
     1443
    12131444} // namespace JSC
    12141445
  • branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r167646 r171605  
    3737#include "JSCell.h"
    3838#include "JSFunction.h"
     39#include "JSPropertyNameEnumerator.h"
    3940#include "JSPropertyNameIterator.h"
    4041#include "JSVariableObject.h"
    4142#include "LinkBuffer.h"
    4243#include "MaxFrameExtentForSlowPathCall.h"
     44#include "RepatchBuffer.h"
    4345#include "SlowPathCall.h"
    4446#include "VirtualRegister.h"
     
    11771179}
    11781180
     1181void JIT::emit_op_get_enumerable_length(Instruction* currentInstruction)
     1182{
     1183    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_enumerable_length);
     1184    slowPathCall.call();
     1185}
     1186
     1187void JIT::emit_op_has_structure_property(Instruction* currentInstruction)
     1188{
     1189    int dst = currentInstruction[1].u.operand;
     1190    int base = currentInstruction[2].u.operand;
     1191    int enumerator = currentInstruction[4].u.operand;
     1192
     1193    emitLoadPayload(base, regT0);
     1194    emitJumpSlowCaseIfNotJSCell(base);
     1195
     1196    emitLoadPayload(enumerator, regT1);
     1197
     1198    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
     1199    addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
     1200   
     1201    move(TrustedImm32(1), regT0);
     1202    emitStoreBool(dst, regT0);
     1203}
     1204
     1205void JIT::emitSlow_op_has_structure_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1206{
     1207    linkSlowCase(iter);
     1208    linkSlowCase(iter);
     1209
     1210    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_structure_property);
     1211    slowPathCall.call();
     1212}
     1213
     1214void JIT::emit_op_has_generic_property(Instruction* currentInstruction)
     1215{
     1216    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_generic_property);
     1217    slowPathCall.call();
     1218}
     1219
     1220void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
     1221{
     1222    Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex;
     1223   
     1224    PatchableJump badType;
     1225   
     1226    // FIXME: Add support for other types like TypedArrays and Arguments.
     1227    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
     1228    JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType);
     1229    move(TrustedImm32(1), regT0);
     1230    Jump done = jump();
     1231
     1232    LinkBuffer patchBuffer(*m_vm, this, m_codeBlock);
     1233   
     1234    patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
     1235    patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
     1236   
     1237    patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
     1238   
     1239    byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
     1240        m_codeBlock, patchBuffer,
     1241        ("Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.value()));
     1242   
     1243    RepatchBuffer repatchBuffer(m_codeBlock);
     1244    repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code()));
     1245    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationHasIndexedPropertyGeneric));
     1246}
     1247
     1248void JIT::emit_op_has_indexed_property(Instruction* currentInstruction)
     1249{
     1250    int dst = currentInstruction[1].u.operand;
     1251    int base = currentInstruction[2].u.operand;
     1252    int property = currentInstruction[3].u.operand;
     1253    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1254   
     1255    emitLoadPayload(base, regT0);
     1256    emitJumpSlowCaseIfNotJSCell(base);
     1257
     1258    emitLoadPayload(property, regT1);
     1259
     1260    // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
     1261    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
     1262    // number was signed since m_vectorLength is always less than intmax (since the total allocation
     1263    // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
     1264    // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
     1265    // extending since it makes it easier to re-tag the value in the slow case.
     1266    zeroExtend32ToPtr(regT1, regT1);
     1267
     1268    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
     1269    and32(TrustedImm32(IndexingShapeMask), regT2);
     1270
     1271    JITArrayMode mode = chooseArrayMode(profile);
     1272    PatchableJump badType;
     1273
     1274    // FIXME: Add support for other types like TypedArrays and Arguments.
     1275    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
     1276    JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType);
     1277    move(TrustedImm32(1), regT0);
     1278
     1279    addSlowCase(badType);
     1280    addSlowCase(slowCases);
     1281   
     1282    Label done = label();
     1283   
     1284    emitStoreBool(dst, regT0);
     1285   
     1286    m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     1287}
     1288
     1289void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1290{
     1291    int dst = currentInstruction[1].u.operand;
     1292    int base = currentInstruction[2].u.operand;
     1293    int property = currentInstruction[3].u.operand;
     1294    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1295   
     1296    linkSlowCaseIfNotJSCell(iter, base); // base cell check
     1297    linkSlowCase(iter); // base array check
     1298   
     1299    Jump skipProfiling = jump();
     1300   
     1301    linkSlowCase(iter); // vector length check
     1302    linkSlowCase(iter); // empty value
     1303   
     1304    emitArrayProfileOutOfBoundsSpecialCase(profile);
     1305   
     1306    skipProfiling.link(this);
     1307   
     1308    Label slowPath = label();
     1309   
     1310    emitLoad(base, regT1, regT0);
     1311    emitLoad(property, regT3, regT2);
     1312    Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2);
     1313
     1314    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
     1315    m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
     1316    m_byValInstructionIndex++;
     1317}
     1318
     1319void JIT::emit_op_get_direct_pname(Instruction* currentInstruction)
     1320{
     1321    int dst = currentInstruction[1].u.operand;
     1322    int base = currentInstruction[2].u.operand;
     1323    int index = currentInstruction[4].u.operand;
     1324    int enumerator = currentInstruction[5].u.operand;
     1325
     1326    // Check that base is a cell
     1327    emitLoadPayload(base, regT0);
     1328    emitJumpSlowCaseIfNotJSCell(base);
     1329
     1330    // Check the structure
     1331    emitLoadPayload(enumerator, regT1);
     1332    load32(Address(regT0, JSCell::structureIDOffset()), regT2);
     1333    addSlowCase(branch32(NotEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
     1334
     1335    // Compute the offset
     1336    emitLoadPayload(index, regT2);
     1337    // If index is less than the enumerator's cached inline storage, then it's an inline access
     1338    Jump outOfLineAccess = branch32(AboveOrEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     1339    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
     1340    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
     1341    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
     1342   
     1343    Jump done = jump();
     1344
     1345    // Otherwise it's out of line
     1346    outOfLineAccess.link(this);
     1347    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
     1348    sub32(Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT2);
     1349    neg32(regT2);
     1350    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
     1351    load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
     1352    load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
     1353   
     1354    done.link(this);
     1355    emitValueProfilingSite();
     1356    emitStore(dst, regT1, regT0);
     1357}
     1358
     1359void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1360{
     1361    int base = currentInstruction[2].u.operand;
     1362    linkSlowCaseIfNotJSCell(iter, base);
     1363    linkSlowCase(iter);
     1364
     1365    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
     1366    slowPathCall.call();
     1367}
     1368
     1369void JIT::emit_op_get_structure_property_enumerator(Instruction* currentInstruction)
     1370{
     1371    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_structure_property_enumerator);
     1372    slowPathCall.call();
     1373}
     1374
     1375void JIT::emit_op_get_generic_property_enumerator(Instruction* currentInstruction)
     1376{
     1377    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_generic_property_enumerator);
     1378    slowPathCall.call();
     1379}
     1380
     1381void JIT::emit_op_next_enumerator_pname(Instruction* currentInstruction)
     1382{
     1383    int dst = currentInstruction[1].u.operand;
     1384    int enumerator = currentInstruction[2].u.operand;
     1385    int index = currentInstruction[3].u.operand;
     1386
     1387    emitLoadPayload(index, regT0);
     1388    emitLoadPayload(enumerator, regT1);
     1389    Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
     1390
     1391    move(TrustedImm32(JSValue::NullTag), regT2);
     1392    move(TrustedImm32(0), regT0);
     1393
     1394    Jump done = jump();
     1395    inBounds.link(this);
     1396
     1397    loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
     1398    loadPtr(BaseIndex(regT1, regT0, timesPtr()), regT0);
     1399    move(TrustedImm32(JSValue::CellTag), regT2);
     1400
     1401    done.link(this);
     1402    emitStore(dst, regT2, regT0);
     1403}
     1404
     1405void JIT::emit_op_to_index_string(Instruction* currentInstruction)
     1406{
     1407    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_index_string);
     1408    slowPathCall.call();
     1409}
     1410
    11791411} // namespace JSC
    11801412
  • branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.cpp

    r171389 r171605  
    4545#include "JSGlobalObjectFunctions.h"
    4646#include "JSNameScope.h"
     47#include "JSPropertyNameEnumerator.h"
    4748#include "JSPropertyNameIterator.h"
    4849#include "JSStackInlines.h"
     
    14991500}
    15001501   
     1502EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
     1503{
     1504    VM& vm = exec->vm();
     1505    NativeCallFrameTracer tracer(&vm, exec);
     1506    JSValue baseValue = JSValue::decode(encodedBase);
     1507    JSValue subscript = JSValue::decode(encodedSubscript);
     1508   
     1509    ASSERT(baseValue.isObject());
     1510    ASSERT(subscript.isUInt32());
     1511
     1512    JSObject* object = asObject(baseValue);
     1513    bool didOptimize = false;
     1514
     1515    unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
     1516    ASSERT(bytecodeOffset);
     1517    ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
     1518    ASSERT(!byValInfo.stubRoutine);
     1519   
     1520    if (hasOptimizableIndexing(object->structure(vm))) {
     1521        // Attempt to optimize.
     1522        JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
     1523        if (arrayMode != byValInfo.arrayMode) {
     1524            JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
     1525            didOptimize = true;
     1526        }
     1527    }
     1528   
     1529    if (!didOptimize) {
     1530        // If we take slow path more than 10 times without patching then make sure we
     1531        // never make that mistake again. Or, if we failed to patch and we have some object
     1532        // that intercepts indexed get, then don't even wait until 10 times. For cases
     1533        // where we see non-index-intercepting objects, this gives 10 iterations worth of
     1534        // opportunity for us to observe that the get_by_val may be polymorphic.
     1535        if (++byValInfo.slowPathCount >= 10
     1536            || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
     1537            // Don't ever try to optimize.
     1538            RepatchBuffer repatchBuffer(exec->codeBlock());
     1539            repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
     1540        }
     1541    }
     1542   
     1543    return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
     1544}
     1545   
     1546EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
     1547{
     1548    VM& vm = exec->vm();
     1549    NativeCallFrameTracer tracer(&vm, exec);
     1550    JSValue baseValue = JSValue::decode(encodedBase);
     1551    JSValue subscript = JSValue::decode(encodedSubscript);
     1552   
     1553    ASSERT(baseValue.isObject());
     1554    ASSERT(subscript.isUInt32());
     1555
     1556    JSObject* object = asObject(baseValue);
     1557    return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
     1558}
     1559   
    15011560EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
    15021561{
     
    17971856    ASSERT(!exec->isVMEntrySentinel());
    17981857    genericUnwind(vm, exec, vm->exception());
     1858}
     1859
     1860int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
     1861{
     1862    VM& vm = exec->vm();
     1863    NativeCallFrameTracer tracer(&vm, exec);
     1864    JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
     1865    return base->methodTable(vm)->getEnumerableLength(exec, base);
     1866}
     1867
     1868EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
     1869{
     1870    VM& vm = exec->vm();
     1871    NativeCallFrameTracer tracer(&vm, exec);
     1872    JSValue baseValue = JSValue::decode(encodedBaseValue);
     1873    if (baseValue.isUndefinedOrNull())
     1874        return JSValue::encode(jsBoolean(false));
     1875
     1876    JSObject* base = baseValue.toObject(exec);
     1877    return JSValue::encode(jsBoolean(base->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
     1878}
     1879
     1880EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
     1881{
     1882    VM& vm = exec->vm();
     1883    NativeCallFrameTracer tracer(&vm, exec);
     1884    JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
     1885    return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
     1886}
     1887   
     1888JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
     1889{
     1890    VM& vm = exec->vm();
     1891    NativeCallFrameTracer tracer(&vm, exec);
     1892       
     1893    JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
     1894    ASSERT(length >= 0);
     1895
     1896    return structurePropertyNameEnumerator(exec, base, static_cast<uint32_t>(length));
     1897}
     1898
     1899JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
     1900{
     1901    VM& vm = exec->vm();
     1902    NativeCallFrameTracer tracer(&vm, exec);
     1903   
     1904    JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
     1905    ASSERT(length >= 0);
     1906
     1907    return genericPropertyNameEnumerator(exec, base, length, jsCast<JSPropertyNameEnumerator*>(structureEnumeratorCell));
     1908}
     1909
     1910EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
     1911{
     1912    VM& vm = exec->vm();
     1913    NativeCallFrameTracer tracer(&vm, exec);
     1914    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
     1915    JSString* propertyName = enumerator->propertyNameAtIndex(index);
     1916    return JSValue::encode(propertyName ? propertyName : jsNull());
     1917}
     1918
     1919JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
     1920{
     1921    VM& vm = exec->vm();
     1922    NativeCallFrameTracer tracer(&vm, exec);
     1923    return jsString(exec, Identifier::from(exec, index).string());
    17991924}
    18001925
  • branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.h

    r170736 r171605  
    9797typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECI)(ExecState*, JSCell*, StringImpl*);
    9898typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
     99typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
    99100typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EDA)(ExecState*, double, JSArray*);
    100101typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EE)(ExecState*, ExecState*);
    101102typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EI)(ExecState*, StringImpl*);
    102103typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJ)(ExecState*, EncodedJSValue);
     104typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
     105typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJC)(ExecState*, EncodedJSValue, JSCell*);
    103106typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
    104107typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJIdc)(ExecState*, EncodedJSValue, const Identifier*);
     
    119122typedef JSCell* JIT_OPERATION (*C_JITOperation_EZ)(ExecState*, int32_t);
    120123typedef JSCell* JIT_OPERATION (*C_JITOperation_EC)(ExecState*, JSCell*);
     124typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
     125typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZC)(ExecState*, JSCell*, int32_t, JSCell*);
    121126typedef JSCell* JIT_OPERATION (*C_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
    122127typedef JSCell* JIT_OPERATION (*C_JITOperation_EIcf)(ExecState*, InlineCallFrame*);
    123128typedef JSCell* JIT_OPERATION (*C_JITOperation_EJ)(ExecState*, EncodedJSValue);
     129typedef JSCell* JIT_OPERATION (*C_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
     130typedef JSCell* JIT_OPERATION (*C_JITOperation_EJZC)(ExecState*, EncodedJSValue, int32_t, JSCell*);
     131typedef JSCell* JIT_OPERATION (*C_JITOperation_EJJC)(ExecState*, EncodedJSValue, EncodedJSValue, JSCell*);
    124132typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssSt)(ExecState*, JSString*, Structure*);
    125133typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssJss)(ExecState*, JSString*, JSString*);
     
    135143typedef int32_t JIT_OPERATION (*Z_JITOperation_D)(double);
    136144typedef int32_t JIT_OPERATION (*Z_JITOperation_E)(ExecState*);
     145typedef int32_t JIT_OPERATION (*Z_JITOperation_EC)(ExecState*, JSCell*);
    137146typedef size_t JIT_OPERATION (*S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
    138147typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
     
    278287EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
    279288EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
     289EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
     290EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
    280291void JIT_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL;
    281292void JIT_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
     
    300311
    301312void JIT_OPERATION operationInitGlobalConst(ExecState*, Instruction*);
     313
     314int32_t JIT_OPERATION operationGetEnumerableLength(ExecState*, JSCell*);
     315EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
     316EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState*, JSCell*, int32_t);
     317JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState*, JSCell*, int32_t);
     318JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState*, JSCell*, int32_t, JSCell*);
     319EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState*, JSCell*, int32_t);
     320JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t);
    302321
    303322} // extern "C"
  • branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r169143 r171605  
    152152}
    153153
    154 JIT::JumpList JIT::emitDoubleGetByVal(Instruction*, PatchableJump& badType)
     154JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump& badType)
    155155{
    156156    JumpList slowCases;
     
    161161    loadDouble(BaseIndex(regT2, regT1, TimesEight), fpRegT0);
    162162    slowCases.append(branchDouble(DoubleNotEqualOrUnordered, fpRegT0, fpRegT0));
    163     moveDoubleTo64(fpRegT0, regT0);
    164     sub64(tagTypeNumberRegister, regT0);
    165163   
    166164    return slowCases;
    167165}
    168166
    169 JIT::JumpList JIT::emitContiguousGetByVal(Instruction*, PatchableJump& badType, IndexingType expectedShape)
     167JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump& badType, IndexingType expectedShape)
    170168{
    171169    JumpList slowCases;
     
    180178}
    181179
    182 JIT::JumpList JIT::emitArrayStorageGetByVal(Instruction*, PatchableJump& badType)
     180JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump& badType)
    183181{
    184182    JumpList slowCases;
  • branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r168443 r171605  
    174174}
    175175
    176 JIT::JumpList JIT::emitContiguousGetByVal(Instruction*, PatchableJump& badType, IndexingType expectedShape)
     176JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump& badType, IndexingType expectedShape)
    177177{
    178178    JumpList slowCases;
    179179   
    180180    badType = patchableBranch32(NotEqual, regT1, TrustedImm32(expectedShape));
    181    
    182181    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
    183182    slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())));
    184    
    185183    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
    186184    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
     
    190188}
    191189
    192 JIT::JumpList JIT::emitDoubleGetByVal(Instruction*, PatchableJump& badType)
     190JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump& badType)
    193191{
    194192    JumpList slowCases;
    195193   
    196194    badType = patchableBranch32(NotEqual, regT1, TrustedImm32(DoubleShape));
    197    
    198195    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
    199196    slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())));
    200    
    201197    loadDouble(BaseIndex(regT3, regT2, TimesEight), fpRegT0);
    202198    slowCases.append(branchDouble(DoubleNotEqualOrUnordered, fpRegT0, fpRegT0));
    203     moveDoubleToInts(fpRegT0, regT0, regT1);
    204199   
    205200    return slowCases;
    206201}
    207202
    208 JIT::JumpList JIT::emitArrayStorageGetByVal(Instruction*, PatchableJump& badType)
     203JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump& badType)
    209204{
    210205    JumpList slowCases;
     
    212207    add32(TrustedImm32(-ArrayStorageShape), regT1, regT3);
    213208    badType = patchableBranch32(Above, regT3, TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape));
    214    
    215209    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
    216210    slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
    217    
    218211    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
    219212    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
  • branches/ftlopt/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r170836 r171605  
    12111211    nativeCallTrampoline(NativeExecutable::m_constructor)
    12121212
     1213_llint_op_get_enumerable_length:
     1214    traceExecution()
     1215    callSlowPath(_slow_path_get_enumerable_length)
     1216    dispatch(3)
     1217
     1218_llint_op_has_indexed_property:
     1219    traceExecution()
     1220    callSlowPath(_slow_path_has_indexed_property)
     1221    dispatch(5)
     1222
     1223_llint_op_has_structure_property:
     1224    traceExecution()
     1225    callSlowPath(_slow_path_has_structure_property)
     1226    dispatch(5)
     1227
     1228_llint_op_has_generic_property:
     1229    traceExecution()
     1230    callSlowPath(_slow_path_has_generic_property)
     1231    dispatch(4)
     1232
     1233_llint_op_get_direct_pname:
     1234    traceExecution()
     1235    callSlowPath(_slow_path_get_direct_pname)
     1236    dispatch(7)
     1237
     1238_llint_op_get_structure_property_enumerator:
     1239    traceExecution()
     1240    callSlowPath(_slow_path_get_structure_property_enumerator)
     1241    dispatch(4)
     1242
     1243_llint_op_get_generic_property_enumerator:
     1244    traceExecution()
     1245    callSlowPath(_slow_path_get_generic_property_enumerator)
     1246    dispatch(5)
     1247
     1248_llint_op_next_enumerator_pname:
     1249    traceExecution()
     1250    callSlowPath(_slow_path_next_enumerator_pname)
     1251    dispatch(4)
     1252
     1253_llint_op_to_index_string:
     1254    traceExecution()
     1255    callSlowPath(_slow_path_to_index_string)
     1256    dispatch(3)
    12131257
    12141258# Lastly, make sure that we can link even though we don't support all opcodes.
  • branches/ftlopt/Source/JavaScriptCore/parser/Nodes.h

    r168107 r171605  
    12811281
    12821282    private:
     1283        RegisterID* tryGetBoundLocal(BytecodeGenerator&);
     1284        void emitLoopHeader(BytecodeGenerator&, RegisterID* propertyName);
     1285        void emitMultiLoopBytecode(BytecodeGenerator&, RegisterID* dst);
     1286
    12831287        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
    12841288    };
  • branches/ftlopt/Source/JavaScriptCore/runtime/Arguments.cpp

    r167729 r171605  
    224224        propertyNames.add(Identifier::from(exec, i));
    225225    }
    226     if (mode == IncludeDontEnumProperties) {
     226    if (shouldIncludeDontEnumProperties(mode)) {
    227227        propertyNames.add(exec->propertyNames().callee);
    228228        propertyNames.add(exec->propertyNames().length);
  • branches/ftlopt/Source/JavaScriptCore/runtime/ClassInfo.h

    r166837 r171605  
    8282    typedef void (*GetPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    8383    GetPropertyNamesFunctionPtr getPropertyNames;
     84
     85    typedef uint32_t (*GetEnumerableLengthFunctionPtr)(ExecState*, JSObject*);
     86    GetEnumerableLengthFunctionPtr getEnumerableLength;
     87
     88    GetPropertyNamesFunctionPtr getStructurePropertyNames;
     89    GetPropertyNamesFunctionPtr getGenericPropertyNames;
    8490
    8591    typedef String (*ClassNameFunctionPtr)(const JSObject*);
     
    138144        &ClassName::getOwnNonIndexPropertyNames, \
    139145        &ClassName::getPropertyNames, \
     146        &ClassName::getEnumerableLength, \
     147        &ClassName::getStructurePropertyNames, \
     148        &ClassName::getGenericPropertyNames, \
    140149        &ClassName::className, \
    141150        &ClassName::customHasInstance, \
  • branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r170564 r171605  
    4545#include "JSGlobalObjectFunctions.h"
    4646#include "JSNameScope.h"
     47#include "JSPropertyNameEnumerator.h"
    4748#include "JSPropertyNameIterator.h"
    4849#include "JSString.h"
     
    543544}
    544545
     546SLOW_PATH_DECL(slow_path_get_enumerable_length)
     547{
     548    BEGIN();
     549    JSValue baseValue = OP(2).jsValue();
     550    if (baseValue.isUndefinedOrNull())
     551        RETURN(jsNumber(0));
     552
     553    JSObject* base = baseValue.toObject(exec);
     554    RETURN(jsNumber(base->methodTable(vm)->getEnumerableLength(exec, base)));
     555}
     556
     557SLOW_PATH_DECL(slow_path_has_indexed_property)
     558{
     559    BEGIN();
     560    JSObject* base = OP(2).jsValue().toObject(exec);
     561    JSValue property = OP(3).jsValue();
     562    pc[4].u.arrayProfile->observeStructure(base->structure(vm));
     563    ASSERT(property.isUInt32());
     564    RETURN(jsBoolean(base->hasProperty(exec, property.asUInt32())));
     565}
     566
     567SLOW_PATH_DECL(slow_path_has_structure_property)
     568{
     569    BEGIN();
     570    JSObject* base = OP(2).jsValue().toObject(exec);
     571    JSValue property = OP(3).jsValue();
     572    ASSERT(property.isString());
     573    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
     574    if (base->structure(vm)->id() == enumerator->cachedStructureID())
     575        RETURN(jsBoolean(true));
     576    RETURN(jsBoolean(base->hasProperty(exec, asString(property.asCell())->toIdentifier(exec))));
     577}
     578
     579SLOW_PATH_DECL(slow_path_has_generic_property)
     580{
     581    BEGIN();
     582    JSObject* base = OP(2).jsValue().toObject(exec);
     583    JSValue property = OP(3).jsValue();
     584    bool result;
     585    if (property.isString())
     586        result = base->hasProperty(exec, asString(property.asCell())->toIdentifier(exec));
     587    else {
     588        ASSERT(property.isUInt32());
     589        result = base->hasProperty(exec, property.asUInt32());
     590    }
     591    RETURN(jsBoolean(result));
     592}
     593
     594SLOW_PATH_DECL(slow_path_get_direct_pname)
     595{
     596    BEGIN();
     597    JSValue baseValue = OP(2).jsValue();
     598    JSValue property = OP(3).jsValue();
     599    ASSERT(property.isString());
     600    RETURN(baseValue.get(exec, property.toString(exec)->toIdentifier(exec)));
     601}
     602
     603SLOW_PATH_DECL(slow_path_get_structure_property_enumerator)
     604{
     605    BEGIN();
     606    JSValue baseValue = OP(2).jsValue();
     607    if (baseValue.isUndefinedOrNull())
     608        RETURN(JSPropertyNameEnumerator::create(vm));
     609       
     610    JSObject* base = baseValue.toObject(exec);
     611    uint32_t length = OP(3).jsValue().asUInt32();
     612
     613    RETURN(structurePropertyNameEnumerator(exec, base, length));
     614}
     615
     616SLOW_PATH_DECL(slow_path_get_generic_property_enumerator)
     617{
     618    BEGIN();
     619    JSValue baseValue = OP(2).jsValue();
     620    if (baseValue.isUndefinedOrNull())
     621        RETURN(JSPropertyNameEnumerator::create(vm));
     622   
     623    JSObject* base = baseValue.toObject(exec);
     624    uint32_t length = OP(3).jsValue().asUInt32();
     625    JSPropertyNameEnumerator* structureEnumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
     626
     627    RETURN(genericPropertyNameEnumerator(exec, base, length, structureEnumerator));
     628}
     629
     630SLOW_PATH_DECL(slow_path_next_enumerator_pname)
     631{
     632    BEGIN();
     633    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
     634    uint32_t index = OP(3).jsValue().asUInt32();
     635    JSString* propertyName = enumerator->propertyNameAtIndex(index);
     636    RETURN(propertyName ? propertyName : jsNull());
     637}
     638
     639SLOW_PATH_DECL(slow_path_to_index_string)
     640{
     641    BEGIN();
     642    RETURN(jsString(exec, Identifier::from(exec, OP(2).jsValue().asUInt32()).string()));
     643}
     644
    545645} // namespace JSC
    546646
  • branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r170855 r171605  
    227227SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
    228228SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
     229SLOW_PATH_HIDDEN_DECL(slow_path_get_enumerable_length);
     230SLOW_PATH_HIDDEN_DECL(slow_path_has_generic_property);
     231SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property);
     232SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property);
     233SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname);
     234SLOW_PATH_HIDDEN_DECL(slow_path_get_structure_property_enumerator);
     235SLOW_PATH_HIDDEN_DECL(slow_path_get_generic_property_enumerator);
     236SLOW_PATH_HIDDEN_DECL(slow_path_next_enumerator_pname);
     237SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
    229238
    230239} // namespace JSC
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSActivation.cpp

    r165676 r171605  
    112112
    113113    CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(thisObject->m_registers));
    114     if (mode == IncludeDontEnumProperties && !thisObject->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
     114    if (shouldIncludeDontEnumProperties(mode) && !thisObject->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
    115115        propertyNames.add(exec->propertyNames().arguments);
    116116
     
    119119        SymbolTable::Map::iterator end = thisObject->symbolTable()->end(locker);
    120120        for (SymbolTable::Map::iterator it = thisObject->symbolTable()->begin(locker); it != end; ++it) {
    121             if (it->value.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
     121            if (it->value.getAttributes() & DontEnum && !shouldIncludeDontEnumProperties(mode))
    122122                continue;
    123123            if (!thisObject->isValid(it->value))
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSArray.cpp

    r170628 r171605  
    228228    JSArray* thisObject = jsCast<JSArray*>(object);
    229229
    230     if (mode == IncludeDontEnumProperties)
     230    if (shouldIncludeDontEnumProperties(mode))
    231231        propertyNames.add(exec->propertyNames().length);
    232232
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBuffer.cpp

    r163844 r171605  
    120120    JSArrayBuffer* thisObject = jsCast<JSArrayBuffer*>(object);
    121121   
    122     if (mode == IncludeDontEnumProperties)
     122    if (shouldIncludeDontEnumProperties(mode))
    123123        array.add(exec->propertyNames().byteLength);
    124124   
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp

    r163844 r171605  
    202202   
    203203    // length/byteOffset/byteLength are DontEnum, at least in Firefox.
    204     if (mode == IncludeDontEnumProperties) {
     204    if (shouldIncludeDontEnumProperties(mode)) {
    205205        array.add(exec->propertyNames().byteOffset);
    206206        array.add(exec->propertyNames().byteLength);
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.cpp

    r166837 r171605  
    237237}
    238238
     239uint32_t JSCell::getEnumerableLength(ExecState*, JSObject*)
     240{
     241    RELEASE_ASSERT_NOT_REACHED();
     242}
     243
     244void JSCell::getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
     245{
     246    RELEASE_ASSERT_NOT_REACHED();
     247}
     248
     249void JSCell::getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
     250{
     251    RELEASE_ASSERT_NOT_REACHED();
     252}
     253
    239254} // namespace JSC
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.h

    r168335 r171605  
    2626#include "CallData.h"
    2727#include "ConstructData.h"
     28#include "EnumerationMode.h"
    2829#include "Heap.h"
    2930#include "IndexingType.h"
     
    4647class PropertyNameArray;
    4748class Structure;
    48 
    49 enum EnumerationMode {
    50     ExcludeDontEnumProperties,
    51     IncludeDontEnumProperties
    52 };
    5349
    5450template<typename T> void* allocateCell(Heap&);
     
    210206    static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    211207    static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     208
     209    static NO_RETURN_DUE_TO_CRASH uint32_t getEnumerableLength(ExecState*, JSObject*);
     210    static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     211    static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     212
    212213    static String className(const JSObject*);
    213214    JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSFunction.cpp

    r170564 r171605  
    391391{
    392392    JSFunction* thisObject = jsCast<JSFunction*>(object);
    393     if (!thisObject->isHostOrBuiltinFunction() && (mode == IncludeDontEnumProperties)) {
     393    if (!thisObject->isHostOrBuiltinFunction() && shouldIncludeDontEnumProperties(mode)) {
    394394        VM& vm = exec->vm();
    395395        // Make sure prototype has been reified.
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h

    r165989 r171605  
    412412    JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
    413413   
    414     if (mode == IncludeDontEnumProperties)
     414    if (shouldIncludeDontEnumProperties(mode))
    415415        array.add(exec->propertyNames().length);
    416416   
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.cpp

    r170855 r171605  
    7676
    7777        for (auto iter = table->begin(vm); iter != table->end(vm); ++iter) {
    78             if ((!(iter->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)) && !((iter->attributes() & BuiltinOrFunction) && didReify))
     78            if ((!(iter->attributes() & DontEnum) || shouldIncludeDontEnumProperties(mode)) && !((iter->attributes() & BuiltinOrFunction) && didReify))
    7979                propertyNames.add(iter.key());
    8080        }
     
    12851285}
    12861286
     1287bool JSObject::hasOwnProperty(ExecState* exec, unsigned propertyName) const
     1288{
     1289    PropertySlot slot(this);
     1290    return const_cast<JSObject*>(this)->methodTable(exec->vm())->getOwnPropertySlotByIndex(const_cast<JSObject*>(this), exec, propertyName, slot);
     1291}
     1292
    12871293bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
    12881294{
     
    14651471void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    14661472{
     1473    if (!shouldIncludeJSObjectPropertyNames(mode)) {
     1474        // We still have to get non-indexed properties from any subclasses of JSObject that have them.
     1475        object->methodTable(exec->vm())->getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
     1476        return;
     1477    }
     1478
    14671479    // Add numeric properties first. That appears to be the accepted convention.
    14681480    // FIXME: Filling PropertyNameArray with an identifier for every integer
     
    14811493            if (!butterfly->contiguous()[i])
    14821494                continue;
    1483             propertyNames.add(Identifier::from(exec, i));
     1495            propertyNames.add(i);
    14841496        }
    14851497        break;
     
    14931505            if (value != value)
    14941506                continue;
    1495             propertyNames.add(Identifier::from(exec, i));
     1507            propertyNames.add(i);
    14961508        }
    14971509        break;
     
    15041516        for (unsigned i = 0; i < usedVectorLength; ++i) {
    15051517            if (storage->m_vector[i])
    1506                 propertyNames.add(Identifier::from(exec, i));
     1518                propertyNames.add(i);
    15071519        }
    15081520       
     
    15131525            SparseArrayValueMap::const_iterator end = map->end();
    15141526            for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
    1515                 if (mode == IncludeDontEnumProperties || !(it->value.attributes & DontEnum))
     1527                if (shouldIncludeDontEnumProperties(mode) || !(it->value.attributes & DontEnum))
    15161528                    keys.uncheckedAppend(static_cast<unsigned>(it->key));
    15171529            }
     
    15191531            std::sort(keys.begin(), keys.end());
    15201532            for (unsigned i = 0; i < keys.size(); ++i)
    1521                 propertyNames.add(Identifier::from(exec, keys[i]));
     1533                propertyNames.add(keys[i]);
    15221534        }
    15231535        break;
     
    15271539        RELEASE_ASSERT_NOT_REACHED();
    15281540    }
    1529    
     1541
    15301542    object->methodTable(exec->vm())->getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
    15311543}
     
    15351547    getClassPropertyNames(exec, object->classInfo(), propertyNames, mode, object->staticFunctionsReified());
    15361548
     1549    if (!shouldIncludeJSObjectPropertyNames(mode))
     1550        return;
     1551   
    15371552    VM& vm = exec->vm();
    1538     bool canCachePropertiesFromStructure = !propertyNames.size();
    15391553    object->structure(vm)->getPropertyNamesFromStructure(vm, propertyNames, mode);
    1540 
    1541     if (canCachePropertiesFromStructure)
    1542         propertyNames.setNumCacheableSlotsForObject(object, propertyNames.size());
    15431554}
    15441555
     
    26532664}
    26542665
     2666uint32_t JSObject::getEnumerableLength(ExecState* exec, JSObject* object)
     2667{
     2668    VM& vm = exec->vm();
     2669    Structure* structure = object->structure(vm);
     2670    if (structure->holesMustForwardToPrototype(vm))
     2671        return 0;
     2672    switch (object->indexingType()) {
     2673    case ALL_BLANK_INDEXING_TYPES:
     2674    case ALL_UNDECIDED_INDEXING_TYPES:
     2675        return 0;
     2676       
     2677    case ALL_INT32_INDEXING_TYPES:
     2678    case ALL_CONTIGUOUS_INDEXING_TYPES: {
     2679        Butterfly* butterfly = object->butterfly();
     2680        unsigned usedLength = butterfly->publicLength();
     2681        for (unsigned i = 0; i < usedLength; ++i) {
     2682            if (!butterfly->contiguous()[i])
     2683                return 0;
     2684        }
     2685        return usedLength;
     2686    }
     2687       
     2688    case ALL_DOUBLE_INDEXING_TYPES: {
     2689        Butterfly* butterfly = object->butterfly();
     2690        unsigned usedLength = butterfly->publicLength();
     2691        for (unsigned i = 0; i < usedLength; ++i) {
     2692            double value = butterfly->contiguousDouble()[i];
     2693            if (value != value)
     2694                return 0;
     2695        }
     2696        return usedLength;
     2697    }
     2698       
     2699    case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
     2700        ArrayStorage* storage = object->m_butterfly->arrayStorage();
     2701        if (storage->m_sparseMap.get())
     2702            return 0;
     2703       
     2704        unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength());
     2705        for (unsigned i = 0; i < usedVectorLength; ++i) {
     2706            if (!storage->m_vector[i])
     2707                return 0;
     2708        }
     2709        return usedVectorLength;
     2710    }
     2711       
     2712    default:
     2713        RELEASE_ASSERT_NOT_REACHED();
     2714        return 0;
     2715    }
     2716}
     2717
     2718void JSObject::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     2719{
     2720    VM& vm = exec->vm();
     2721    object->structure(vm)->getPropertyNamesFromStructure(vm, propertyNames, mode);
     2722}
     2723
     2724void JSObject::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     2725{
     2726    VM& vm = exec->vm();
     2727    object->methodTable(vm)->getOwnPropertyNames(object, exec, propertyNames, modeThatSkipsJSObject(mode));
     2728
     2729    if (object->prototype().isNull())
     2730        return;
     2731
     2732    JSObject* prototype = asObject(object->prototype());
     2733    while (true) {
     2734        if (prototype->structure(vm)->typeInfo().overridesGetPropertyNames()) {
     2735            prototype->methodTable(vm)->getPropertyNames(prototype, exec, propertyNames, mode);
     2736            break;
     2737        }
     2738        prototype->methodTable(vm)->getOwnPropertyNames(prototype, exec, propertyNames, mode);
     2739        JSValue nextProto = prototype->prototype();
     2740        if (nextProto.isNull())
     2741            break;
     2742        prototype = asObject(nextProto);
     2743    }
     2744}
     2745
     2746
    26552747} // namespace JSC
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h

    r170855 r171605  
    463463    JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
    464464    bool hasOwnProperty(ExecState*, PropertyName) const;
     465    bool hasOwnProperty(ExecState*, unsigned) const;
    465466
    466467    JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
     
    475476    JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    476477    JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     478
     479    JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(ExecState*, JSObject*);
     480    JS_EXPORT_PRIVATE static void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     481    JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    477482
    478483    JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.cpp

    r164764 r171605  
    119119}
    120120
     121uint32_t JSProxy::getEnumerableLength(ExecState* exec, JSObject* object)
     122{
     123    JSProxy* thisObject = jsCast<JSProxy*>(object);
     124    return thisObject->target()->methodTable(exec->vm())->getEnumerableLength(exec, thisObject->target());
     125}
     126
     127void JSProxy::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     128{
     129    JSProxy* thisObject = jsCast<JSProxy*>(object);
     130    thisObject->target()->methodTable(exec->vm())->getStructurePropertyNames(thisObject->target(), exec, propertyNames, mode);
     131}
     132
     133void JSProxy::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     134{
     135    JSProxy* thisObject = jsCast<JSProxy*>(object);
     136    thisObject->target()->methodTable(exec->vm())->getGenericPropertyNames(thisObject->target(), exec, propertyNames, mode);
     137}
     138
    121139void JSProxy::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    122140{
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.h

    r167963 r171605  
    8484    JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    8585    JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     86    JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(ExecState*, JSObject*);
     87    JS_EXPORT_PRIVATE static void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     88    JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    8689    JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
    8790
  • branches/ftlopt/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp

    r165676 r171605  
    6767            if (it->key->isEmptyUnique())
    6868                continue;
    69             if (!(it->value.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
     69            if (!(it->value.getAttributes() & DontEnum) || shouldIncludeDontEnumProperties(mode))
    7070                propertyNames.add(Identifier(exec, it->key.get()));
    7171        }
  • branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.cpp

    r165999 r171605  
    2424#include "JSCInlines.h"
    2525#include "JSObject.h"
     26#include "JSPropertyNameEnumerator.h"
    2627#include "Structure.h"
    2728#include "StructureChain.h"
     
    2930namespace JSC {
    3031
    31 static const size_t setThreshold = 20;
    32 
    3332void PropertyNameArray::add(StringImpl* identifier)
    3433{
    3534    ASSERT(!identifier || identifier == StringImpl::empty() || identifier->isAtomic());
     35    if (!ASSERT_DISABLED) {
     36        uint32_t index = PropertyName(Identifier(m_vm, identifier)).asIndex();
     37        ASSERT_UNUSED(index, index == PropertyName::NotAnIndex || index >= m_previouslyEnumeratedLength);
     38    }
    3639
    37     size_t size = m_data->propertyNameVector().size();
    38     if (size < setThreshold) {
    39         for (size_t i = 0; i < size; ++i) {
    40             if (identifier == m_data->propertyNameVector()[i].impl())
    41                 return;
    42         }
    43     } else {
    44         if (m_set.isEmpty()) {
    45             for (size_t i = 0; i < size; ++i)
    46                 m_set.add(m_data->propertyNameVector()[i].impl());
    47         }
    48         if (!m_set.add(identifier).isNewEntry)
    49             return;
    50     }
     40    if (m_alternateSet && m_alternateSet->contains(identifier))
     41        return;
     42
     43    if (!m_set->add(identifier).isNewEntry)
     44        return;
    5145
    5246    addKnownUnique(identifier);
    5347}
    5448
     49void PropertyNameArray::setPreviouslyEnumeratedProperties(const JSPropertyNameEnumerator* enumerator)
     50{
     51    m_alternateSet = enumerator->identifierSet();
     52}
     53
    5554} // namespace JSC
  • branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.h

    r157653 r171605  
    2929namespace JSC {
    3030   
     31    class JSPropertyNameEnumerator;
    3132    class Structure;
    3233    class StructureChain;
     34
     35    class RefCountedIdentifierSet : public RefCounted<RefCountedIdentifierSet> {
     36    public:
     37        typedef HashSet<StringImpl*, PtrHash<StringImpl*>> Set;
     38
     39        bool contains(StringImpl* impl) const { return m_set.contains(impl); }
     40        size_t size() const  { return m_set.size(); }
     41        Set::AddResult add(StringImpl* impl) { return m_set.add(impl); }
     42
     43    private:
     44        Set m_set;
     45    };
    3346
    3447    // FIXME: Rename to PropertyNameArray.
     
    5467        PropertyNameArray(VM* vm)
    5568            : m_data(PropertyNameArrayData::create())
     69            , m_set(adoptRef(new RefCountedIdentifierSet))
    5670            , m_vm(vm)
    5771            , m_numCacheableSlots(0)
    5872            , m_baseObject(0)
     73            , m_previouslyEnumeratedLength(0)
    5974        {
    6075        }
     
    6277        PropertyNameArray(ExecState* exec)
    6378            : m_data(PropertyNameArrayData::create())
     79            , m_set(adoptRef(new RefCountedIdentifierSet))
    6480            , m_vm(&exec->vm())
    6581            , m_numCacheableSlots(0)
    6682            , m_baseObject(0)
     83            , m_previouslyEnumeratedLength(0)
    6784        {
    6885        }
     
    7087        VM* vm() { return m_vm; }
    7188
     89        void add(uint32_t index)
     90        {
     91            if (index < m_previouslyEnumeratedLength)
     92                return;
     93            add(Identifier::from(m_vm, index));
     94        }
     95
    7296        void add(const Identifier& identifier) { add(identifier.impl()); }
    7397        JS_EXPORT_PRIVATE void add(StringImpl*);
    74         void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_vm, identifier)); }
     98        void addKnownUnique(StringImpl* identifier)
     99        {
     100            m_set->add(identifier);
     101            m_data->propertyNameVector().append(Identifier(m_vm, identifier));
     102        }
    75103
    76104        Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
     
    81109        PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
    82110
     111        RefCountedIdentifierSet* identifierSet() const { return m_set.get(); }
     112
    83113        // FIXME: Remove these functions.
     114        bool canAddKnownUniqueForStructure() const { return !m_set->size() && (!m_alternateSet || !m_alternateSet->size()); }
    84115        typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
    85116        size_t size() const { return m_data->propertyNameVector().size(); }
     
    101132        }
    102133
     134        void setPreviouslyEnumeratedLength(uint32_t length) { m_previouslyEnumeratedLength = length; }
     135        void setPreviouslyEnumeratedProperties(const JSPropertyNameEnumerator*);
     136
    103137    private:
    104         typedef HashSet<StringImpl*, PtrHash<StringImpl*>> IdentifierSet;
    105 
    106138        RefPtr<PropertyNameArrayData> m_data;
    107         IdentifierSet m_set;
     139        RefPtr<RefCountedIdentifierSet> m_set;
     140        RefPtr<RefCountedIdentifierSet> m_alternateSet;
    108141        VM* m_vm;
    109142        size_t m_numCacheableSlots;
    110143        JSObject* m_baseObject;
     144        uint32_t m_previouslyEnumeratedLength;
    111145    };
    112146
  • branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.cpp

    r163844 r171605  
    110110void RegExpObject::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    111111{
    112     if (mode == IncludeDontEnumProperties)
     112    if (shouldIncludeDontEnumProperties(mode))
    113113        propertyNames.add(exec->propertyNames().lastIndex);
    114114    Base::getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
     
    117117void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    118118{
    119     if (mode == IncludeDontEnumProperties)
     119    if (shouldIncludeDontEnumProperties(mode))
    120120        propertyNames.add(exec->propertyNames().lastIndex);
    121121    Base::getPropertyNames(object, exec, propertyNames, mode);
     122}
     123
     124void RegExpObject::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     125{
     126    if (shouldIncludeDontEnumProperties(mode))
     127        propertyNames.add(exec->propertyNames().lastIndex);
     128    Base::getGenericPropertyNames(object, exec, propertyNames, mode);
    122129}
    123130
  • branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.h

    r156668 r171605  
    7878        JS_EXPORT_PRIVATE void finishCreation(VM&);
    7979
    80         static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags;
     80        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags;
    8181
    8282        static void visitChildren(JSCell*, SlotVisitor&);
     
    8585        JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    8686        JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     87        JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
    8788        JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
    8889
  • branches/ftlopt/Source/JavaScriptCore/runtime/StringObject.cpp

    r163844 r171605  
    151151    for (int i = 0; i < size; ++i)
    152152        propertyNames.add(Identifier::from(exec, i));
    153     if (mode == IncludeDontEnumProperties)
     153    if (shouldIncludeDontEnumProperties(mode))
    154154        propertyNames.add(exec->propertyNames().length);
    155155    return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
  • branches/ftlopt/Source/JavaScriptCore/runtime/Structure.cpp

    r171510 r171605  
    3131#include "JSCInlines.h"
    3232#include "JSObject.h"
    33 #include "JSPropertyNameIterator.h"
     33#include "JSPropertyNameEnumerator.h"
    3434#include "Lookup.h"
    3535#include "PropertyMapHashTable.h"
     
    957957        return;
    958958
    959     bool knownUnique = !propertyNames.size();
     959    bool knownUnique = propertyNames.canAddKnownUniqueForStructure();
    960960
    961961    PropertyTable::iterator end = propertyTable()->end();
    962962    for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
    963963        ASSERT(hasNonEnumerableProperties() || !(iter->attributes & DontEnum));
    964         if (!iter->key->isEmptyUnique() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) {
     964        if (!iter->key->isEmptyUnique() && (!(iter->attributes & DontEnum) || shouldIncludeDontEnumProperties(mode))) {
    965965            if (knownUnique)
    966966                propertyNames.addKnownUnique(iter->key);
     
    12611261}
    12621262
     1263void Structure::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
     1264{
     1265    ASSERT(!isDictionary());
     1266    if (!hasRareData())
     1267        allocateRareData(vm);
     1268    rareData()->setCachedStructurePropertyNameEnumerator(vm, enumerator);
     1269}
     1270
     1271JSPropertyNameEnumerator* Structure::cachedStructurePropertyNameEnumerator() const
     1272{
     1273    if (!hasRareData())
     1274        return nullptr;
     1275    return rareData()->cachedStructurePropertyNameEnumerator();
     1276}
     1277
     1278void Structure::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
     1279{
     1280    ASSERT(!isDictionary());
     1281    if (!hasRareData())
     1282        allocateRareData(vm);
     1283    rareData()->setCachedGenericPropertyNameEnumerator(vm, enumerator);
     1284}
     1285
     1286JSPropertyNameEnumerator* Structure::cachedGenericPropertyNameEnumerator() const
     1287{
     1288    if (!hasRareData())
     1289        return nullptr;
     1290    return rareData()->cachedGenericPropertyNameEnumerator();
     1291}
     1292
     1293bool Structure::canCacheStructurePropertyNameEnumerator() const
     1294{
     1295    if (isDictionary())
     1296        return false;
     1297    return true;
     1298}
     1299
     1300bool Structure::canCacheGenericPropertyNameEnumerator() const
     1301{
     1302    if (!canCacheStructurePropertyNameEnumerator())
     1303        return false;
     1304
     1305    if (hasIndexedProperties(indexingType()))
     1306        return false;
     1307
     1308    StructureChain* structureChain = m_cachedPrototypeChain.get();
     1309    ASSERT(structureChain);
     1310    WriteBarrier<Structure>* structure = structureChain->head();
     1311    while (true) {
     1312        if (!structure->get())
     1313            break;
     1314        if (structure->get()->typeInfo().overridesGetPropertyNames())
     1315            return false;
     1316        structure++;
     1317    }
     1318
     1319    return true;
     1320}
     1321
     1322bool Structure::canAccessPropertiesQuickly() const
     1323{
     1324    if (hasNonEnumerableProperties())
     1325        return false;
     1326    if (hasGetterSetterProperties())
     1327        return false;
     1328    if (isUncacheableDictionary())
     1329        return false;
     1330    return true;
     1331}
     1332
    12631333} // namespace JSC
  • branches/ftlopt/Source/JavaScriptCore/runtime/Structure.h

    r171510 r171605  
    284284    void setEnumerationCache(VM&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
    285285    JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
     286
     287    void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
     288    void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
     289    JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
     290    JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
     291    bool canCacheStructurePropertyNameEnumerator() const;
     292    bool canCacheGenericPropertyNameEnumerator() const;
     293    bool canAccessPropertiesQuickly() const;
     294
    286295    void getPropertyNamesFromStructure(VM&, PropertyNameArray&, EnumerationMode);
    287296
  • branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.cpp

    r170855 r171605  
    2727#include "StructureRareData.h"
    2828
     29#include "JSPropertyNameEnumerator.h"
    2930#include "JSPropertyNameIterator.h"
    3031#include "JSString.h"
     
    6970    visitor.append(&thisObject->m_objectToStringValue);
    7071    visitor.append(&thisObject->m_enumerationCache);
     72    visitor.append(&thisObject->m_cachedStructurePropertyNameEnumerator);
     73    visitor.append(&thisObject->m_cachedGenericPropertyNameEnumerator);
     74}
     75
     76JSPropertyNameEnumerator* StructureRareData::cachedStructurePropertyNameEnumerator() const
     77{
     78    return m_cachedStructurePropertyNameEnumerator.get();
     79}
     80
     81void StructureRareData::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
     82{
     83    m_cachedStructurePropertyNameEnumerator.set(vm, this, enumerator);
     84}
     85
     86JSPropertyNameEnumerator* StructureRareData::cachedGenericPropertyNameEnumerator() const
     87{
     88    return m_cachedGenericPropertyNameEnumerator.get();
     89}
     90
     91void StructureRareData::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
     92{
     93    m_cachedGenericPropertyNameEnumerator.set(vm, this, enumerator);
    7194}
    7295
  • branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.h

    r170855 r171605  
    3434namespace JSC {
    3535
     36class JSPropertyNameEnumerator;
    3637class JSPropertyNameIterator;
    3738class Structure;
     
    6263    DECLARE_EXPORT_INFO;
    6364
     65    JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
     66    JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
     67    void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
     68    void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
     69
    6470private:
    6571    friend class Structure;
     
    7278    WriteBarrier<JSString> m_objectToStringValue;
    7379    WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
     80    WriteBarrier<JSPropertyNameEnumerator> m_cachedStructurePropertyNameEnumerator;
     81    WriteBarrier<JSPropertyNameEnumerator> m_cachedGenericPropertyNameEnumerator;
    7482   
    7583    typedef HashMap<PropertyOffset, RefPtr<WatchpointSet>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> PropertyWatchpointMap;
  • branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp

    r171510 r171605  
    6565#include "JSPromiseDeferred.h"
    6666#include "JSPromiseReaction.h"
     67#include "JSPropertyNameEnumerator.h"
    6768#include "JSPropertyNameIterator.h"
    6869#include "JSWithScope.h"
     
    259260    notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
    260261    propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull()));
     262    propertyNameEnumeratorStructure.set(*this, JSPropertyNameEnumerator::createStructure(*this, 0, jsNull()));
    261263    getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull()));
    262264    apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull()));
  • branches/ftlopt/Source/JavaScriptCore/runtime/VM.h

    r171510 r171605  
    267267        Strong<Structure> notAnObjectStructure;
    268268        Strong<Structure> propertyNameIteratorStructure;
     269        Strong<Structure> propertyNameEnumeratorStructure;
    269270        Strong<Structure> getterSetterStructure;
    270271        Strong<Structure> apiWrapperStructure;
     
    292293#endif
    293294        Strong<JSCell> iterationTerminator;
     295        Strong<JSCell> emptyPropertyNameEnumerator;
    294296
    295297        AtomicStringTable* m_atomicStringTable;
  • branches/ftlopt/Source/WebCore/ChangeLog

    r170680 r171605  
     12014-07-23  Mark Hahnenberg  <[email protected]>
     2
     3        Refactor our current implementation of for-in
     4        https://bugs.webkit.org/show_bug.cgi?id=134142
     5
     6        Reviewed by Filip Pizlo.
     7
     8        No new tests.
     9
     10        This patch splits for-in loops into three distinct parts:
     11
     12        - Iterating over the indexed properties in the base object.
     13        - Iterating over the Structure properties in the base object.
     14        - Iterating over any other enumerable properties for that object and any objects in the prototype chain.
     15 
     16        It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to
     17        support the various operations required for each loop.
     18
     19        * bindings/js/JSDOMWindowCustom.cpp:
     20        (WebCore::JSDOMWindow::getEnumerableLength):
     21        (WebCore::JSDOMWindow::getStructurePropertyNames):
     22        (WebCore::JSDOMWindow::getGenericPropertyNames):
     23        * bindings/scripts/CodeGeneratorJS.pm:
     24        (GenerateHeader):
     25        * bridge/runtime_array.cpp:
     26        (JSC::RuntimeArray::getOwnPropertyNames):
     27
    1282014-07-01  Mark Lam  <[email protected]>
    229
  • branches/ftlopt/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp

    r167794 r171605  
    382382}
    383383
     384uint32_t JSDOMWindow::getEnumerableLength(ExecState* exec, JSObject* object)
     385{
     386    JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
     387    // Only allow the window to enumerated by frames in the same origin.
     388    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
     389        return 0;
     390    return Base::getEnumerableLength(exec, thisObject);
     391}
     392
     393void JSDOMWindow::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     394{
     395    JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
     396    // Only allow the window to enumerated by frames in the same origin.
     397    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
     398        return;
     399    Base::getStructurePropertyNames(thisObject, exec, propertyNames, mode);
     400}
     401
     402void JSDOMWindow::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
     403{
     404    JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
     405    // Only allow the window to enumerated by frames in the same origin.
     406    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
     407        return;
     408    Base::getGenericPropertyNames(thisObject, exec, propertyNames, mode);
     409}
     410
    384411void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    385412{
  • branches/ftlopt/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r170564 r171605  
    973973    if ($interfaceName eq "DOMWindow") {
    974974        push(@headerContent, "    static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
     975        push(@headerContent, "    static void getGenericPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
     976        push(@headerContent, "    static void getStructurePropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
     977        push(@headerContent, "    static uint32_t getEnumerableLength(JSC::ExecState*, JSC::JSObject*);\n");
    975978        $structureFlags{"JSC::OverridesGetPropertyNames"} = 1;
    976979    }
  • branches/ftlopt/Source/WebCore/bridge/runtime_array.cpp

    r165676 r171605  
    8282        propertyNames.add(Identifier::from(exec, i));
    8383
    84     if (mode == IncludeDontEnumProperties)
     84    if (shouldIncludeDontEnumProperties(mode))
    8585        propertyNames.add(exec->propertyNames().length);
    8686
  • branches/ftlopt/Source/WebKit2/ChangeLog

    r168513 r171605  
     12014-07-23  Mark Hahnenberg  <[email protected]>
     2
     3        Refactor our current implementation of for-in
     4        https://bugs.webkit.org/show_bug.cgi?id=134142
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * WebProcess/Plugins/Netscape/JSNPObject.cpp:
     9        (WebKit::JSNPObject::invalidate): Fixed an invalid ASSERT that was crashing in debug builds.
     10
    1112014-05-08  Simon Fraser  <[email protected]>
    212
  • branches/ftlopt/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp

    r166091 r171605  
    9191{
    9292    ASSERT(m_npObject);
    93     ASSERT_GC_OBJECT_INHERITS(this, info());
    9493
    9594    releaseNPObject(m_npObject);
Note: See TracChangeset for help on using the changeset viewer.