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);