Array checks should use the structure, not the class info
https://bugs.webkit.org/show_bug.cgi?id=93150
Reviewed by Mark Hahnenberg.
This changes all array checks used in array accesses (get, put, get length,
push, pop) to use the structure, not the class info. Additionally, these
checks in the LLInt and baseline JIT record the structure in an ArrayProfile,
so that the DFG can know exactly what structure to check for.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/ArrayProfile.cpp: Added.
(JSC):
(JSC::ArrayProfile::computeUpdatedPrediction):
* bytecode/ArrayProfile.h: Added.
(JSC):
(JSC::arrayModeFromStructure):
(ArrayProfile):
(JSC::ArrayProfile::ArrayProfile):
(JSC::ArrayProfile::bytecodeOffset):
(JSC::ArrayProfile::addressOfLastSeenStructure):
(JSC::ArrayProfile::observeStructure):
(JSC::ArrayProfile::expectedStructure):
(JSC::ArrayProfile::structureIsPolymorphic):
(JSC::ArrayProfile::hasDefiniteStructure):
(JSC::ArrayProfile::observedArrayModes):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::getArrayProfile):
(JSC):
(JSC::CodeBlock::getOrAddArrayProfile):
(JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::executionEntryCount):
(JSC::CodeBlock::numberOfArrayProfiles):
(JSC::CodeBlock::arrayProfiles):
(JSC::CodeBlock::addArrayProfile):
(CodeBlock):
* bytecode/Instruction.h:
(JSC):
(JSC::Instruction::Instruction):
* bytecode/Opcode.h:
(JSC):
(JSC::padOpcodeName):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitGetArgumentByVal):
(JSC::BytecodeGenerator::emitGetByVal):
(JSC::BytecodeGenerator::emitPutByVal):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::execute):
* dfg/DFGAbstractValue.h:
(JSC::DFG::StructureAbstractValue::hasSingleton):
(StructureAbstractValue):
(JSC::DFG::StructureAbstractValue::singleton):
* dfg/DFGArgumentsSimplificationPhase.cpp:
(JSC::DFG::ArgumentsSimplificationPhase::run):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::speculateArray):
(DFG):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureCheckHoistingPhase.cpp:
(JSC::DFG::StructureCheckHoistingPhase::run):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::privateCompilePatchGetArrayLength):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::privateCompilePatchGetArrayLength):
* llint/LLIntOffsetsExtractor.cpp:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/Structure.h:
(Structure):
(JSC::Structure::classInfoOffset):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@125637 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 4e3cd57..f7b10fc 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -96,9 +96,29 @@
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
#endif
- if (isArray)
+ if (isArray) {
node.setOp(GetArrayLength);
- else if (isArguments)
+ ASSERT(node.flags() & NodeMustGenerate);
+ node.clearFlags(NodeMustGenerate);
+ m_graph.deref(m_compileIndex);
+
+ ArrayProfile* arrayProfile =
+ m_graph.baselineCodeBlockFor(node.codeOrigin)->getArrayProfile(
+ node.codeOrigin.bytecodeIndex);
+ if (!arrayProfile)
+ break;
+ arrayProfile->computeUpdatedPrediction();
+ if (!arrayProfile->hasDefiniteStructure())
+ break;
+ m_graph.ref(node.child1());
+ Node checkStructure(CheckStructure, node.codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), node.child1().index());
+ checkStructure.ref();
+ NodeIndex checkStructureIndex = m_graph.size();
+ m_graph.append(checkStructure);
+ m_insertionSet.append(m_indexInBlock, checkStructureIndex);
+ break;
+ }
+ if (isArguments)
node.setOp(GetArgumentsLength);
else if (isString)
node.setOp(GetStringLength);
@@ -129,10 +149,9 @@
break;
}
case GetIndexedPropertyStorage: {
- SpeculatedType basePrediction = m_graph[node.child2()].prediction();
- if ((!(basePrediction & SpecInt32) && basePrediction)
- || m_graph[node.child1()].shouldSpeculateArguments()
- || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
+ if (!m_graph[node.child1()].prediction()
+ || !m_graph[node.child2()].shouldSpeculateInteger()
+ || m_graph[node.child1()].shouldSpeculateArguments()) {
node.setOpAndDefaultFlags(Nop);
m_graph.clearAndDerefChild1(node);
m_graph.clearAndDerefChild2(node);