Changeset 128219 in webkit
- Timestamp:
- Sep 11, 2012 1:00:31 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r128191 r128219 1 2012-09-11 Filip Pizlo <fpizlo@apple.com> 2 3 LLInt should optimize and profile array length accesses 4 https://bugs.webkit.org/show_bug.cgi?id=96417 5 6 Reviewed by Oliver Hunt. 7 8 This fixes the following hole in our array profiling strategy, where the array 9 is large (more than 1000 elements): 10 11 for (var i = 0; i < array.length; ++i) ... 12 13 The peeled use of array.length (in the array prologue) will execute only once 14 before DFG optimization kicks in from the loop's OSR point. Since it executed 15 only once, it executed in the LLInt. And prior to this patch, the LLInt did 16 not profile array.length accesses - so the DFG will assume, based on the lack 17 of profiling, that the access is in fact not an access to the JSArray length 18 property. That could then impede our ability to hoist the array structure 19 check, and may make us pessimistic in other ways as well, since the generic 20 GetById used for the array length access will be viewed as a side-effecting 21 operation. 22 23 * bytecode/CodeBlock.cpp: 24 (JSC::CodeBlock::printGetByIdCacheStatus): 25 (JSC::CodeBlock::finalizeUnconditionally): 26 * bytecode/GetByIdStatus.cpp: 27 (JSC::GetByIdStatus::computeFromLLInt): 28 * dfg/DFGByteCodeParser.cpp: 29 (JSC::DFG::ByteCodeParser::parseBlock): 30 * dfg/DFGCapabilities.h: 31 (JSC::DFG::canCompileOpcode): 32 * dfg/DFGFixupPhase.cpp: 33 (JSC::DFG::FixupPhase::fixupNode): 34 * jit/JIT.cpp: 35 (JSC::JIT::privateCompileMainPass): 36 (JSC::JIT::privateCompileSlowCases): 37 * llint/LLIntSlowPaths.cpp: 38 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 39 * llint/LowLevelInterpreter.asm: 40 * llint/LowLevelInterpreter32_64.asm: 41 * llint/LowLevelInterpreter64.asm: 42 1 43 2012-09-11 Raphael Kubo da Costa <rakuco@webkit.org> 2 44 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r128096 r128219 292 292 293 293 #if ENABLE(LLINT) 294 Structure* structure = instruction[4].u.structure.get(); 295 dataLog(" llint("); 296 dumpStructure("struct", exec, structure, ident); 297 dataLog(")"); 294 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length) 295 dataLog(" llint(array_length)"); 296 else { 297 Structure* structure = instruction[4].u.structure.get(); 298 dataLog(" llint("); 299 dumpStructure("struct", exec, structure, ident); 300 dataLog(")"); 301 } 298 302 #endif 299 303 … … 2082 2086 curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id); 2083 2087 break; 2088 case op_get_array_length: 2089 break; 2084 2090 default: 2085 2091 ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r127333 r128219 44 44 if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_method_check)) 45 45 instruction++; 46 47 if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_get_array_length)) 48 return GetByIdStatus(NoInformation, false); 46 49 47 50 Structure* structure = instruction[4].u.structure.get(); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r128111 r128219 2277 2277 } 2278 2278 case op_get_by_id: 2279 case op_get_by_id_out_of_line: { 2279 case op_get_by_id_out_of_line: 2280 case op_get_array_length: { 2280 2281 SpeculatedType prediction = getPrediction(); 2281 2282 -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r121925 r128219 121 121 case op_get_by_id: 122 122 case op_get_by_id_out_of_line: 123 case op_get_array_length: 123 124 case op_put_by_id: 124 125 case op_put_by_id_out_of_line: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r126715 r128219 93 93 fromObserved(arrayProfile->observedArrayModes(), false), 94 94 m_graph[node.child1()].prediction(), 95 m_graph[m_compileIndex].prediction()); 95 m_graph[m_compileIndex].prediction()); 96 96 if (modeSupportsLength(arrayMode) && arrayProfile->hasDefiniteStructure()) { 97 97 m_graph.ref(nodePtr->child1()); -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r127393 r128219 257 257 DEFINE_OP(op_eq_null) 258 258 case op_get_by_id_out_of_line: 259 case op_get_array_length: 259 260 DEFINE_OP(op_get_by_id) 260 261 DEFINE_OP(op_get_arguments_length) … … 359 360 DEFINE_OP(op_to_primitive) 360 361 361 case op_get_array_length:362 362 case op_get_by_id_chain: 363 363 case op_get_by_id_generic: … … 447 447 DEFINE_SLOWCASE_OP(op_eq) 448 448 case op_get_by_id_out_of_line: 449 case op_get_array_length: 449 450 DEFINE_SLOWCASE_OP(op_get_by_id) 450 451 DEFINE_SLOWCASE_OP(op_get_arguments_length) -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r128096 r128219 859 859 LLINT_CHECK_EXCEPTION(); 860 860 LLINT_OP(1) = result; 861 861 862 862 if (!LLINT_ALWAYS_ACCESS_SLOW 863 863 && baseValue.isCell() … … 881 881 } 882 882 } 883 } 884 885 if (!LLINT_ALWAYS_ACCESS_SLOW 886 && isJSArray(baseValue) 887 && ident == exec->propertyNames().length) { 888 pc[0].u.opcode = LLInt::getOpcode(llint_op_get_array_length); 889 #if ENABLE(VALUE_PROFILER) 890 ArrayProfile* arrayProfile = codeBlock->getOrAddArrayProfile(pc - codeBlock->instructions().begin()); 891 arrayProfile->observeStructure(baseValue.asCell()->structure()); 892 pc[4].u.arrayProfile = arrayProfile; 893 #endif 883 894 } 884 895 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r128146 r128219 846 846 end 847 847 848 _llint_op_get_array_length:849 notSupported()850 851 848 _llint_op_get_by_id_chain: 852 849 notSupported() -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r128146 r128219 1167 1167 _llint_op_get_by_id_out_of_line: 1168 1168 getById(withOutOfLineStorage) 1169 1170 1171 _llint_op_get_array_length: 1172 traceExecution() 1173 loadi 8[PC], t0 1174 loadp 16[PC], t1 1175 loadConstantOrVariablePayload(t0, CellTag, t3, .opGetArrayLengthSlot) 1176 loadp JSCell::m_structure[t3], t2 1177 if VALUE_PROFILER 1178 storep t2, ArrayProfile::m_lastSeenStructure[t1] 1179 end 1180 loadp CodeBlock[cfr], t1 1181 loadp CodeBlock::m_globalData[t1], t1 1182 loadp JSGlobalData::jsArrayClassInfo[t1], t1 1183 bpneq Structure::m_classInfo[t2], t1, .opGetArrayLengthSlow 1184 loadi 4[PC], t1 1185 loadp 32[PC], t2 1186 loadp JSArray::m_storage[t3], t0 1187 loadi ArrayStorage::m_length[t0], t0 1188 bilt t0, 0, .opGetArrayLengthSlow 1189 valueProfile(Int32Tag, t0, t2) 1190 storep t0, PayloadOffset[cfr, t1, 8] 1191 storep Int32Tag, TagOffset[cfr, t1, 8] 1192 dispatch(9) 1193 1194 .opGetArrayLengthSlow: 1195 callSlowPath(_llint_slow_path_get_by_id) 1196 dispatch(9) 1169 1197 1170 1198 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r128146 r128219 1014 1014 _llint_op_get_by_id_out_of_line: 1015 1015 getById(withOutOfLineStorage) 1016 1017 1018 _llint_op_get_array_length: 1019 traceExecution() 1020 loadis 16[PB, PC, 8], t0 1021 loadp 32[PB, PC, 8], t1 1022 loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow) 1023 loadp JSCell::m_structure[t3], t2 1024 if VALUE_PROFILER 1025 storep t2, ArrayProfile::m_lastSeenStructure[t1] 1026 end 1027 loadp CodeBlock[cfr], t1 1028 loadp CodeBlock::m_globalData[t1], t1 1029 loadp JSGlobalData::jsArrayClassInfo[t1], t1 1030 bpneq Structure::m_classInfo[t2], t1, .opGetArrayLengthSlow 1031 loadis 8[PB, PC, 8], t1 1032 loadp 64[PB, PC, 8], t2 1033 loadp JSArray::m_storage[t3], t0 1034 loadi ArrayStorage::m_length[t0], t0 1035 bilt t0, 0, .opGetArrayLengthSlow 1036 orp tagTypeNumber, t0 1037 valueProfile(t0, t2) 1038 storep t0, [cfr, t1, 8] 1039 dispatch(9) 1040 1041 .opGetArrayLengthSlow: 1042 callSlowPath(_llint_slow_path_get_by_id) 1043 dispatch(9) 1016 1044 1017 1045
Note: See TracChangeset
for help on using the changeset viewer.