Changeset 126715 in webkit
- Timestamp:
- Aug 26, 2012 3:35:26 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r126712 r126715 1 2012-08-26 Filip Pizlo <fpizlo@apple.com> 2 3 Array type checks and storage accesses should be uniformly represented and available to CSE 4 https://bugs.webkit.org/show_bug.cgi?id=95013 5 6 Reviewed by Oliver Hunt. 7 8 This uniformly breaks up all array accesses into up to three parts: 9 10 1) The type check, using a newly introduced CheckArray node, in addition to possibly 11 a CheckStructure node. We were already inserting the CheckStructure prior to this 12 patch. The CheckArray node will be automatically eliminated if the thing it was 13 checking for had already been checked for, either intentionally (a CheckStructure 14 inserted based on the array profile of this access) or accidentally (some checks, 15 typically a CheckStructure, inserted for some unrelated operations). The 16 CheckArray node may not be inserted if the array type is non-specific (Generic or 17 ForceExit). 18 19 2) The storage load using GetIndexedPropertyStorage. Previously, this only worked for 20 GetByVal. Now it works for all array accesses. The storage load may not be 21 inserted if the mode of array access does not permit CSE of storage loads (like 22 non-specific modes or Arguments). 23 24 3) The access itself: one of GetByVal, PutByVal, PutByValAlias, ArrayPush, ArrayPop, 25 GetArrayLength, StringCharAt, or StringCharCodeAt. 26 27 This means that the type check can be subjected to CSE even if the CFA isn't smart 28 enough to reason about it (yet!). It also means that the storage load can always be 29 subjected to CSE; previously CSE on storage load only worked for array loads and not 30 other forms of access. Finally, it removes the bizarre behavior that 31 GetIndexedPropertyStorage previously had: previously, it was responsible for the type 32 check in some cases, but not others; this made reasoning about the CFA really 33 confusing. 34 35 This change also disables late refinement of array mode, since I decided that 36 supporting that feature is both confusing and likely unprofitable. The array modes are 37 now locked in in the first fixup run after prediction propagation. Of course, 38 refinements from Generic to something else would not have been a problem; we could 39 reenable those if we thought we really needed to. 40 41 * dfg/DFGAbstractState.cpp: 42 (JSC::DFG::AbstractState::execute): 43 * dfg/DFGArgumentsSimplificationPhase.cpp: 44 (JSC::DFG::ArgumentsSimplificationPhase::run): 45 * dfg/DFGArrayMode.cpp: 46 (JSC::DFG::fromStructure): 47 (DFG): 48 (JSC::DFG::refineArrayMode): 49 * dfg/DFGArrayMode.h: 50 (DFG): 51 (JSC::DFG::modeIsJSArray): 52 (JSC::DFG::lengthNeedsStorage): 53 (JSC::DFG::modeIsSpecific): 54 (JSC::DFG::modeSupportsLength): 55 * dfg/DFGByteCodeParser.cpp: 56 (JSC::DFG::ByteCodeParser::ByteCodeParser): 57 (JSC::DFG::ByteCodeParser::getArrayMode): 58 (ByteCodeParser): 59 (JSC::DFG::ByteCodeParser::getArrayModeAndEmitChecks): 60 (JSC::DFG::ByteCodeParser::handleIntrinsic): 61 (JSC::DFG::ByteCodeParser::parseBlock): 62 * dfg/DFGCFGSimplificationPhase.cpp: 63 (JSC::DFG::CFGSimplificationPhase::mergeBlocks): 64 * dfg/DFGCSEPhase.cpp: 65 (JSC::DFG::CSEPhase::CSEPhase): 66 (JSC::DFG::CSEPhase::checkStructureElimination): 67 (CSEPhase): 68 (JSC::DFG::CSEPhase::checkArrayElimination): 69 (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): 70 (JSC::DFG::CSEPhase::performNodeCSE): 71 (JSC::DFG::performCSE): 72 * dfg/DFGCSEPhase.h: 73 (DFG): 74 * dfg/DFGCommon.h: 75 * dfg/DFGConstantFoldingPhase.cpp: 76 (JSC::DFG::ConstantFoldingPhase::foldConstants): 77 * dfg/DFGDriver.cpp: 78 (JSC::DFG::compile): 79 * dfg/DFGFixupPhase.cpp: 80 (JSC::DFG::FixupPhase::fixupNode): 81 (JSC::DFG::FixupPhase::checkArray): 82 (FixupPhase): 83 (JSC::DFG::FixupPhase::blessArrayOperation): 84 * dfg/DFGGraph.cpp: 85 (JSC::DFG::Graph::Graph): 86 (DFG): 87 (JSC::DFG::Graph::dump): 88 (JSC::DFG::Graph::collectGarbage): 89 * dfg/DFGGraph.h: 90 (Graph): 91 (JSC::DFG::Graph::vote): 92 (JSC::DFG::Graph::substitute): 93 * dfg/DFGNode.h: 94 (JSC::DFG::Node::hasArrayMode): 95 (JSC::DFG::Node::setArrayMode): 96 * dfg/DFGNodeType.h: 97 (DFG): 98 * dfg/DFGOperations.cpp: 99 * dfg/DFGPhase.h: 100 (DFG): 101 * dfg/DFGPredictionPropagationPhase.cpp: 102 (JSC::DFG::PredictionPropagationPhase::propagate): 103 (JSC::DFG::PredictionPropagationPhase::mergeDefaultFlags): 104 * dfg/DFGSpeculativeJIT.cpp: 105 (JSC::DFG::SpeculativeJIT::checkArray): 106 (JSC::DFG::SpeculativeJIT::useChildren): 107 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 108 (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray): 109 (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage): 110 (JSC::DFG::SpeculativeJIT::compileGetArrayLength): 111 * dfg/DFGSpeculativeJIT.h: 112 (SpeculativeJIT): 113 * dfg/DFGSpeculativeJIT32_64.cpp: 114 (JSC::DFG::SpeculativeJIT::compile): 115 * dfg/DFGSpeculativeJIT64.cpp: 116 (JSC::DFG::SpeculativeJIT::compile): 117 * dfg/DFGStructureCheckHoistingPhase.cpp: 118 (JSC::DFG::StructureCheckHoistingPhase::run): 119 1 120 2012-08-26 Filip Pizlo <fpizlo@apple.com> 2 121 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r126494 r126715 888 888 break; 889 889 case Array::String: 890 forNode(node.child1()).filter(SpecString);891 890 forNode(node.child2()).filter(SpecInt32); 892 891 forNode(nodeIndex).set(SpecString); 893 892 break; 894 893 case Array::Arguments: 895 forNode(node.child1()).filter(SpecArguments);896 894 forNode(node.child2()).filter(SpecInt32); 897 895 forNode(nodeIndex).makeTop(); … … 901 899 // FIXME: We should have more conservative handling of the out-of-bounds 902 900 // case. 903 forNode(node.child1()).filter(SpecCell);904 901 forNode(node.child2()).filter(SpecInt32); 905 902 forNode(nodeIndex).makeTop(); 906 903 break; 907 904 case Array::Int8Array: 908 forNode(node.child1()).filter(SpecInt8Array);909 905 forNode(node.child2()).filter(SpecInt32); 910 906 forNode(nodeIndex).set(SpecInt32); 911 907 break; 912 908 case Array::Int16Array: 913 forNode(node.child1()).filter(SpecInt16Array);914 909 forNode(node.child2()).filter(SpecInt32); 915 910 forNode(nodeIndex).set(SpecInt32); 916 911 break; 917 912 case Array::Int32Array: 918 forNode(node.child1()).filter(SpecInt32Array);919 913 forNode(node.child2()).filter(SpecInt32); 920 914 forNode(nodeIndex).set(SpecInt32); 921 915 break; 922 916 case Array::Uint8Array: 923 forNode(node.child1()).filter(SpecUint8Array);924 917 forNode(node.child2()).filter(SpecInt32); 925 918 forNode(nodeIndex).set(SpecInt32); 926 919 break; 927 920 case Array::Uint8ClampedArray: 928 forNode(node.child1()).filter(SpecUint8ClampedArray);929 921 forNode(node.child2()).filter(SpecInt32); 930 922 forNode(nodeIndex).set(SpecInt32); 931 923 break; 932 924 case Array::Uint16Array: 933 forNode(node.child1()).filter(SpecUint16Array);934 925 forNode(node.child2()).filter(SpecInt32); 935 926 forNode(nodeIndex).set(SpecInt32); 936 927 break; 937 928 case Array::Uint32Array: 938 forNode(node.child1()).filter(SpecUint32Array);939 929 forNode(node.child2()).filter(SpecInt32); 940 930 if (node.shouldSpeculateInteger()) … … 944 934 break; 945 935 case Array::Float32Array: 946 forNode(node.child1()).filter(SpecFloat32Array);947 936 forNode(node.child2()).filter(SpecInt32); 948 937 forNode(nodeIndex).set(SpecDouble); 949 938 break; 950 939 case Array::Float64Array: 951 forNode(node.child1()).filter(SpecFloat64Array);952 940 forNode(node.child2()).filter(SpecInt32); 953 941 forNode(nodeIndex).set(SpecDouble); … … 960 948 case PutByValAlias: { 961 949 node.setCanExit(true); 962 Edge child1 = m_graph.varArgChild(node, 0);963 950 Edge child2 = m_graph.varArgChild(node, 1); 964 951 Edge child3 = m_graph.varArgChild(node, 2); … … 971 958 break; 972 959 case Array::JSArray: 973 forNode(child1).filter(SpecCell);974 960 forNode(child2).filter(SpecInt32); 975 961 break; 976 962 case Array::JSArrayOutOfBounds: 977 forNode(child1).filter(SpecCell);978 963 forNode(child2).filter(SpecInt32); 979 964 clobberWorld(node.codeOrigin, indexInBlock); 980 965 break; 981 966 case Array::Arguments: 982 forNode(child1).filter(SpecArguments);983 967 forNode(child2).filter(SpecInt32); 984 968 break; 985 969 case Array::Int8Array: 986 forNode(child1).filter(SpecInt8Array);987 970 forNode(child2).filter(SpecInt32); 988 971 if (m_graph[child3].shouldSpeculateInteger()) … … 992 975 break; 993 976 case Array::Int16Array: 994 forNode(child1).filter(SpecInt16Array);995 977 forNode(child2).filter(SpecInt32); 996 978 if (m_graph[child3].shouldSpeculateInteger()) … … 1000 982 break; 1001 983 case Array::Int32Array: 1002 forNode(child1).filter(SpecInt32Array);1003 984 forNode(child2).filter(SpecInt32); 1004 985 if (m_graph[child3].shouldSpeculateInteger()) … … 1008 989 break; 1009 990 case Array::Uint8Array: 1010 forNode(child1).filter(SpecUint8Array);1011 991 forNode(child2).filter(SpecInt32); 1012 992 if (m_graph[child3].shouldSpeculateInteger()) … … 1016 996 break; 1017 997 case Array::Uint8ClampedArray: 1018 forNode(child1).filter(SpecUint8ClampedArray);1019 998 forNode(child2).filter(SpecInt32); 1020 999 if (m_graph[child3].shouldSpeculateInteger()) … … 1024 1003 break; 1025 1004 case Array::Uint16Array: 1026 forNode(child1).filter(SpecUint16Array);1027 1005 forNode(child2).filter(SpecInt32); 1028 1006 if (m_graph[child3].shouldSpeculateInteger()) … … 1032 1010 break; 1033 1011 case Array::Uint32Array: 1034 forNode(child1).filter(SpecUint32Array);1035 1012 forNode(child2).filter(SpecInt32); 1036 1013 if (m_graph[child3].shouldSpeculateInteger()) … … 1040 1017 break; 1041 1018 case Array::Float32Array: 1042 forNode(child1).filter(SpecFloat32Array);1043 1019 forNode(child2).filter(SpecInt32); 1044 1020 forNode(child3).filter(SpecNumber); 1045 1021 break; 1046 1022 case Array::Float64Array: 1047 forNode(child1).filter(SpecFloat64Array);1048 1023 forNode(child2).filter(SpecInt32); 1049 1024 forNode(child3).filter(SpecNumber); … … 1058 1033 case ArrayPush: 1059 1034 node.setCanExit(true); 1060 forNode(node.child1()).filter(SpecCell);1061 1035 forNode(nodeIndex).set(SpecNumber); 1062 1036 break; … … 1064 1038 case ArrayPop: 1065 1039 node.setCanExit(true); 1066 forNode(node.child1()).filter(SpecCell);1067 1040 forNode(nodeIndex).makeTop(); 1068 1041 break; … … 1348 1321 1349 1322 case GetArrayLength: 1350 switch (node.arrayMode()) { 1351 case Array::Undecided: 1352 ASSERT_NOT_REACHED(); 1353 break; 1354 case Array::ForceExit: 1355 m_isValid = false; 1356 break; 1357 case Array::Generic: 1358 ASSERT_NOT_REACHED(); 1359 break; 1360 case Array::String: 1361 node.setCanExit(!isStringSpeculation(forNode(node.child1()).m_type)); 1362 forNode(node.child1()).filter(SpecString); 1363 forNode(nodeIndex).set(SpecInt32); 1364 break; 1365 case Array::JSArray: 1366 node.setCanExit(true); 1367 forNode(node.child1()).filter(SpecCell); 1368 forNode(nodeIndex).set(SpecInt32); 1369 break; 1370 case Array::JSArrayOutOfBounds: 1371 ASSERT_NOT_REACHED(); 1372 break; 1373 case Array::Arguments: 1374 node.setCanExit(true); 1375 forNode(node.child1()).filter(SpecArguments); 1376 forNode(nodeIndex).set(SpecInt32); 1377 break; 1378 case Array::Int8Array: 1379 node.setCanExit(!isInt8ArraySpeculation(forNode(node.child1()).m_type)); 1380 forNode(node.child1()).filter(SpecInt8Array); 1381 forNode(nodeIndex).set(SpecInt32); 1382 break; 1383 case Array::Int16Array: 1384 node.setCanExit(!isInt16ArraySpeculation(forNode(node.child1()).m_type)); 1385 forNode(node.child1()).filter(SpecInt16Array); 1386 forNode(nodeIndex).set(SpecInt32); 1387 break; 1388 case Array::Int32Array: 1389 node.setCanExit(!isInt32ArraySpeculation(forNode(node.child1()).m_type)); 1390 forNode(node.child1()).filter(SpecInt32Array); 1391 forNode(nodeIndex).set(SpecInt32); 1392 break; 1393 case Array::Uint8Array: 1394 node.setCanExit(!isUint8ArraySpeculation(forNode(node.child1()).m_type)); 1395 forNode(node.child1()).filter(SpecUint8Array); 1396 forNode(nodeIndex).set(SpecInt32); 1397 break; 1398 case Array::Uint8ClampedArray: 1399 node.setCanExit(!isUint8ClampedArraySpeculation(forNode(node.child1()).m_type)); 1400 forNode(node.child1()).filter(SpecUint8ClampedArray); 1401 forNode(nodeIndex).set(SpecInt32); 1402 break; 1403 case Array::Uint16Array: 1404 node.setCanExit(!isUint16ArraySpeculation(forNode(node.child1()).m_type)); 1405 forNode(node.child1()).filter(SpecUint16Array); 1406 forNode(nodeIndex).set(SpecInt32); 1407 break; 1408 case Array::Uint32Array: 1409 node.setCanExit(!isUint32ArraySpeculation(forNode(node.child1()).m_type)); 1410 forNode(node.child1()).filter(SpecUint32Array); 1411 forNode(nodeIndex).set(SpecInt32); 1412 break; 1413 case Array::Float32Array: 1414 node.setCanExit(!isFloat32ArraySpeculation(forNode(node.child1()).m_type)); 1415 forNode(node.child1()).filter(SpecFloat32Array); 1416 forNode(nodeIndex).set(SpecInt32); 1417 break; 1418 case Array::Float64Array: 1419 node.setCanExit(!isFloat64ArraySpeculation(forNode(node.child1()).m_type)); 1420 forNode(node.child1()).filter(SpecFloat64Array); 1421 forNode(nodeIndex).set(SpecInt32); 1422 break; 1423 } 1323 node.setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough. 1324 forNode(nodeIndex).set(SpecInt32); 1424 1325 break; 1425 1326 … … 1493 1394 forNode(nodeIndex).clear(); // The result is not a JS value. 1494 1395 break; 1495 case GetIndexedPropertyStorage: { 1496 node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise. 1396 case CheckArray: { 1397 if (modeAlreadyChecked(forNode(node.child1()), node.arrayMode())) { 1398 m_foundConstants = true; 1399 node.setCanExit(false); 1400 break; 1401 } 1402 node.setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here. 1497 1403 switch (node.arrayMode()) { 1498 1404 case Array::String: … … 1505 1411 forNode(node.child1()).filter(SpecCell); 1506 1412 break; 1413 case Array::Arguments: 1414 forNode(node.child1()).filter(SpecArguments); 1415 break; 1507 1416 case Array::Int8Array: 1508 1417 forNode(node.child1()).filter(SpecInt8Array); … … 1534 1443 default: 1535 1444 ASSERT_NOT_REACHED(); 1445 break; 1446 } 1447 break; 1448 } 1449 case GetIndexedPropertyStorage: { 1450 switch (node.arrayMode()) { 1451 case Array::String: 1452 // Strings are weird - we may spec fail if the string was a rope. That is of course 1453 // stupid, and we should fix that, but for now let's at least be honest about it. 1454 node.setCanExit(true); 1455 break; 1456 default: 1457 node.setCanExit(false); 1536 1458 break; 1537 1459 } -
trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
r126387 r126715 313 313 case StructureTransitionWatchpoint: 314 314 case ForwardStructureTransitionWatchpoint: 315 case CheckArray: 315 316 // We don't care about these because if we get uses of the relevant 316 317 // variable then we can safely get rid of these, too. This of course … … 477 478 case ForwardCheckStructure: 478 479 case StructureTransitionWatchpoint: 479 case ForwardStructureTransitionWatchpoint: { 480 case ForwardStructureTransitionWatchpoint: 481 case CheckArray: { 480 482 // We can just get rid of this node, if it references a phantom argument. 481 483 if (!isOKToOptimize(m_graph[node.child1()])) -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
r126387 r126715 52 52 } 53 53 54 Array::Mode fromStructure(Structure* structure, bool makeSafe) 55 { 56 return fromObserved(arrayModeFromStructure(structure), makeSafe); 57 } 58 54 59 Array::Mode refineArrayMode(Array::Mode arrayMode, SpeculatedType base, SpeculatedType index) 55 60 { … … 65 70 return Array::Generic; 66 71 67 // Pass through any array modes that would have been decided by the array profile, since 68 // the predictions of the inputs will not tell us anything useful that we didn't already 69 // get from the array profile. 70 switch (arrayMode) { 71 case Array::ForceExit: 72 case Array::JSArray: 73 case Array::JSArrayOutOfBounds: 72 if (arrayMode != Array::Undecided) 74 73 return arrayMode; 75 default:76 break;77 }78 74 79 75 if (isStringSpeculation(base)) -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h
r126387 r126715 64 64 Array::Mode fromObserved(ArrayModes modes, bool makeSafe); 65 65 66 Array::Mode fromStructure(Structure*, bool makeSafe); 67 66 68 Array::Mode refineArrayMode(Array::Mode, SpeculatedType base, SpeculatedType index); 67 69 … … 69 71 70 72 const char* modeToString(Array::Mode); 73 74 inline bool modeIsJSArray(Array::Mode arrayMode) 75 { 76 switch (arrayMode) { 77 case Array::JSArray: 78 case Array::JSArrayOutOfBounds: 79 return true; 80 default: 81 return false; 82 } 83 } 71 84 72 85 inline bool canCSEStorage(Array::Mode arrayMode) … … 81 94 return true; 82 95 } 96 } 97 98 inline bool lengthNeedsStorage(Array::Mode arrayMode) 99 { 100 return modeIsJSArray(arrayMode); 83 101 } 84 102 … … 116 134 } 117 135 118 inline bool mode SupportsLength(Array::Mode mode)136 inline bool modeIsSpecific(Array::Mode mode) 119 137 { 120 138 switch (mode) { … … 128 146 } 129 147 148 inline bool modeSupportsLength(Array::Mode mode) 149 { 150 return modeIsSpecific(mode); 151 } 152 130 153 } } // namespace JSC::DFG 131 154 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r126695 r126715 72 72 , m_haveBuiltOperandMaps(false) 73 73 , m_emptyJSValueIndex(UINT_MAX) 74 , m_currentInstruction(0) 74 75 { 75 76 ASSERT(m_profiledBlock); … … 819 820 } 820 821 821 Array::Mode getArrayModeWithoutOSRExit(Instruction* currentInstruction, NodeIndex base) 822 { 823 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 822 Array::Mode getArrayMode(ArrayProfile* profile) 823 { 824 profile->computeUpdatedPrediction(); 825 return fromObserved(profile->observedArrayModes(), false); 826 } 827 828 Array::Mode getArrayModeAndEmitChecks(ArrayProfile* profile, NodeIndex base) 829 { 824 830 profile->computeUpdatedPrediction(); 825 831 if (profile->hasDefiniteStructure()) … … 839 845 } 840 846 841 Array::Mode getArrayMode(Instruction* currentInstruction, NodeIndex base)842 {843 Array::Mode result = getArrayModeWithoutOSRExit(currentInstruction, base);844 845 if (result == Array::ForceExit)846 addToGraph(ForceOSRExit);847 848 return result;849 }850 851 847 NodeIndex makeSafe(NodeIndex nodeIndex) 852 848 { … … 1151 1147 // Cache of code blocks that we've generated bytecode for. 1152 1148 ByteCodeCache<canInlineFunctionFor> m_codeBlockCache; 1149 1150 Instruction* m_currentInstruction; 1153 1151 }; 1154 1152 … … 1554 1552 return false; 1555 1553 1556 NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); 1554 Array::Mode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile); 1555 if (!modeIsJSArray(arrayMode)) 1556 return false; 1557 NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); 1557 1558 if (usesResult) 1558 1559 set(resultOperand, arrayPush); … … 1565 1566 return false; 1566 1567 1567 NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); 1568 Array::Mode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile); 1569 if (!modeIsJSArray(arrayMode)) 1570 return false; 1571 NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); 1568 1572 if (usesResult) 1569 1573 set(resultOperand, arrayPop); … … 1793 1797 // Switch on the current bytecode opcode. 1794 1798 Instruction* currentInstruction = instructionsBegin + m_currentIndex; 1799 m_currentInstruction = currentInstruction; // Some methods want to use this, and we'd rather not thread it through calls. 1795 1800 OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode); 1796 1801 switch (opcodeID) { … … 2178 2183 2179 2184 NodeIndex base = get(currentInstruction[2].u.operand); 2180 Array::Mode arrayMode = getArrayMode (currentInstruction, base);2185 Array::Mode arrayMode = getArrayModeAndEmitChecks(currentInstruction[4].u.arrayProfile, base); 2181 2186 NodeIndex property = get(currentInstruction[3].u.operand); 2182 2187 NodeIndex getByVal = addToGraph(GetByVal, OpInfo(arrayMode), OpInfo(prediction), base, property); … … 2189 2194 NodeIndex base = get(currentInstruction[1].u.operand); 2190 2195 2191 Array::Mode arrayMode = getArrayMode (currentInstruction, base);2196 Array::Mode arrayMode = getArrayModeAndEmitChecks(currentInstruction[4].u.arrayProfile, base); 2192 2197 2193 2198 NodeIndex property = get(currentInstruction[2].u.operand); … … 2197 2202 addVarArgChild(property); 2198 2203 addVarArgChild(value); 2204 addVarArgChild(NoNode); // Leave room for property storage. 2199 2205 addToGraph(Node::VarArg, PutByVal, OpInfo(arrayMode), OpInfo(0)); 2200 2206 -
trunk/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
r126494 r126715 660 660 for (unsigned childIdx = node.firstChild(); 661 661 childIdx < node.firstChild() + node.numChildren(); 662 ++childIdx) 663 fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef); 662 ++childIdx) { 663 if (!!m_graph.m_varArgChildren[childIdx]) 664 fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef); 665 } 664 666 } else if (!!node.child1()) { 665 667 fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef); -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r126387 r126715 36 36 class CSEPhase : public Phase { 37 37 public: 38 CSEPhase(Graph& graph , OptimizationFixpointState fixpointState)38 CSEPhase(Graph& graph) 39 39 : Phase(graph, "common subexpression elimination") 40 , m_fixpointState(fixpointState)41 40 { 42 41 // Replacements are used to implement local common subexpression elimination. … … 328 327 } 329 328 330 bool checkStructure LoadElimination(const StructureSet& structureSet, NodeIndex child1)329 bool checkStructureElimination(const StructureSet& structureSet, NodeIndex child1) 331 330 { 332 331 for (unsigned i = m_indexInBlock; i--;) { … … 625 624 return NoNode; 626 625 } 627 628 NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, bool hasIntegerIndexPrediction)626 627 bool checkArrayElimination(NodeIndex child1, Array::Mode arrayMode) 629 628 { 630 629 for (unsigned i = m_indexInBlock; i--;) { … … 635 634 Node& node = m_graph[index]; 636 635 switch (node.op()) { 636 case PutByOffset: 637 case PutStructure: 638 // Changing the structure or putting to the storage cannot 639 // change the property storage pointer. 640 break; 641 642 case CheckArray: 643 if (node.child1() == child1 && node.arrayMode() == arrayMode) 644 return true; 645 break; 646 647 default: 648 if (m_graph.clobbersWorld(index)) 649 return false; 650 break; 651 } 652 } 653 return false; 654 } 655 656 NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, Array::Mode arrayMode) 657 { 658 for (unsigned i = m_indexInBlock; i--;) { 659 NodeIndex index = m_currentBlock->at(i); 660 if (index == child1) 661 break; 662 663 Node& node = m_graph[index]; 664 switch (node.op()) { 637 665 case GetIndexedPropertyStorage: { 638 SpeculatedType basePrediction = m_graph[node.child2()].prediction(); 639 bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction); 640 if (node.child1() == child1 && hasIntegerIndexPrediction == nodeHasIntegerIndexPrediction) 666 if (node.child1() == child1 && node.arrayMode() == arrayMode) 641 667 return index; 642 668 break; … … 989 1015 // FIXME: We should be able to remove SetLocals that can exit; we just need 990 1016 // to replace them with appropriate type checks. 991 if (m_ fixpointState == FixpointNotConverged) {1017 if (m_graph.m_fixpointState == FixpointNotConverged) { 992 1018 // Need to be conservative at this time; if the SetLocal has any chance of performing 993 1019 // any speculations then we cannot do anything. … … 1078 1104 case PutGlobalVar: 1079 1105 case PutGlobalVarCheck: 1080 if (m_ fixpointState == FixpointNotConverged)1106 if (m_graph.m_fixpointState == FixpointNotConverged) 1081 1107 break; 1082 1108 eliminate(globalVarStoreElimination(node.registerPointer())); … … 1104 1130 case CheckStructure: 1105 1131 case ForwardCheckStructure: 1106 if (checkStructure LoadElimination(node.structureSet(), node.child1().index()))1132 if (checkStructureElimination(node.structureSet(), node.child1().index())) 1107 1133 eliminate(); 1108 1134 break; … … 1115 1141 1116 1142 case PutStructure: 1117 if (m_ fixpointState == FixpointNotConverged)1143 if (m_graph.m_fixpointState == FixpointNotConverged) 1118 1144 break; 1119 1145 eliminate(putStructureStoreElimination(node.child1().index()), PhantomPutStructure); … … 1125 1151 break; 1126 1152 1153 case CheckArray: 1154 if (checkArrayElimination(node.child1().index(), node.arrayMode())) 1155 eliminate(); 1156 break; 1157 1127 1158 case GetIndexedPropertyStorage: { 1128 SpeculatedType basePrediction = m_graph[node.child2()].prediction(); 1129 bool nodeHasIntegerIndexPrediction = !(!(basePrediction & SpecInt32) && basePrediction); 1130 setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), nodeHasIntegerIndexPrediction)); 1159 setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), node.arrayMode())); 1131 1160 break; 1132 1161 } … … 1141 1170 1142 1171 case PutByOffset: 1143 if (m_ fixpointState == FixpointNotConverged)1172 if (m_graph.m_fixpointState == FixpointNotConverged) 1144 1173 break; 1145 1174 eliminate(putByOffsetStoreElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index())); … … 1179 1208 Vector<NodeIndex, 16> m_replacements; 1180 1209 FixedArray<unsigned, LastNodeType> m_lastSeen; 1181 OptimizationFixpointState m_fixpointState;1182 1210 bool m_changed; // Only tracks changes that have a substantive effect on other optimizations. 1183 1211 }; 1184 1212 1185 bool performCSE(Graph& graph , OptimizationFixpointState fixpointState)1213 bool performCSE(Graph& graph) 1186 1214 { 1187 1215 SamplingRegion samplingRegion("DFG CSE Phase"); 1188 return runPhase<CSEPhase>(graph , fixpointState);1216 return runPhase<CSEPhase>(graph); 1189 1217 } 1190 1218 -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.h
r118468 r126715 42 42 // on a few benchmarks, and is relatively cheap to run. 43 43 44 bool performCSE(Graph& , OptimizationFixpointState);44 bool performCSE(Graph&); 45 45 46 46 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r121798 r126715 133 133 enum NoResultTag { NoResult }; 134 134 135 enum OptimizationFixpointState { FixpointConverged, FixpointNotConverged };135 enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged }; 136 136 137 137 inline bool shouldShowDisassembly() -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r125999 r126715 102 102 break; 103 103 } 104 104 105 case CheckArray: { 106 if (!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode())) 107 break; 108 ASSERT(node.refCount() == 1); 109 node.setOpAndDefaultFlags(Phantom); 110 eliminated = true; 111 break; 112 } 113 105 114 default: 106 115 break; -
trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp
r126689 r126715 117 117 performStructureCheckHoisting(dfg); 118 118 unsigned cnt = 1; 119 dfg.m_fixpointState = FixpointNotConverged; 119 120 for (;; ++cnt) { 120 121 #if DFG_ENABLE(DEBUG_VERBOSE) … … 126 127 changed |= performArgumentsSimplification(dfg); 127 128 changed |= performCFGSimplification(dfg); 128 changed |= performCSE(dfg , FixpointNotConverged);129 changed |= performCSE(dfg); 129 130 if (!changed) 130 131 break; … … 132 133 performFixup(dfg); 133 134 } 134 performCSE(dfg, FixpointConverged); 135 dfg.m_fixpointState = FixpointConverged; 136 performCSE(dfg); 135 137 #if DFG_ENABLE(DEBUG_VERBOSE) 136 138 dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt); -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r126387 r126715 75 75 switch (op) { 76 76 case GetById: { 77 if (m_graph.m_fixpointState > BeforeFixpoint) 78 break; 79 77 80 Node* nodePtr = &node; 78 81 … … 91 94 m_graph[node.child1()].prediction(), 92 95 m_graph[m_compileIndex].prediction()); 93 if (modeSupportsLength(arrayMode) 94 && arrayProfile->hasDefiniteStructure()) { 96 if (modeSupportsLength(arrayMode) && arrayProfile->hasDefiniteStructure()) { 95 97 m_graph.ref(nodePtr->child1()); 96 98 Node checkStructure(CheckStructure, nodePtr->codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), nodePtr->child1().index()); … … 114 116 m_graph.deref(m_compileIndex); 115 117 nodePtr->setArrayMode(arrayMode); 118 119 NodeIndex storage = checkArray(arrayMode, nodePtr->codeOrigin, nodePtr->child1().index(), lengthNeedsStorage, nodePtr->shouldGenerate()); 120 if (storage == NoNode) 121 break; 122 123 nodePtr = &m_graph[m_compileIndex]; 124 nodePtr->children.child2() = Edge(storage); 116 125 break; 117 126 } 118 127 case GetIndexedPropertyStorage: { 119 node.setArrayMode(120 refineArrayMode(121 node.arrayMode(),122 m_graph[node.child1()].prediction(),123 m_graph[node.child2()].prediction()));124 // Predictions should only become more, rather than less, refined. Hence125 // if we were ever able to CSE the storage pointer for this operation,126 // then we should always continue to be able to do so.127 128 ASSERT(canCSEStorage(node.arrayMode())); 128 129 break; … … 137 138 m_graph[node.child2()].prediction())); 138 139 139 if (canCSEStorage(node.arrayMode())) { 140 if (node.child3()) { 141 ASSERT(m_graph[node.child3()].op() == GetIndexedPropertyStorage); 142 ASSERT(modesCompatibleForStorageLoad(m_graph[node.child3()].arrayMode(), node.arrayMode())); 143 } else { 144 // Make sure we don't use the node reference after we do the append. 145 Node getIndexedPropertyStorage( 146 GetIndexedPropertyStorage, node.codeOrigin, OpInfo(node.arrayMode()), 147 node.child1().index(), node.child2().index()); 148 NodeIndex getIndexedPropertyStorageIndex = m_graph.size(); 149 node.children.child3() = Edge(getIndexedPropertyStorageIndex); 150 m_graph.append(getIndexedPropertyStorage); 151 m_graph.ref(getIndexedPropertyStorageIndex); // Once because it's MustGenerate. 152 m_graph.ref(getIndexedPropertyStorageIndex); // And again because it's referenced from the GetByVal. 153 m_insertionSet.append(m_indexInBlock, getIndexedPropertyStorageIndex); 154 } 155 } else { 156 // See above. Continued fixup of the graph should not regress our ability 157 // to speculate. 158 ASSERT(!node.child3()); 159 } 160 break; 140 blessArrayOperation(node.child1(), 2); 141 break; 142 } 143 144 case ArrayPush: { 145 blessArrayOperation(node.child1(), 2); 146 break; 147 } 148 149 case ArrayPop: { 150 blessArrayOperation(node.child1(), 1); 161 151 } 162 152 … … 331 321 Edge child2 = m_graph.varArgChild(node, 1); 332 322 Edge child3 = m_graph.varArgChild(node, 2); 323 333 324 node.setArrayMode( 334 325 refineArrayMode( 335 node.arrayMode(), m_graph[child1].prediction(), m_graph[child2].prediction())); 336 337 switch (modeForPut(node.arrayMode())) { 326 node.arrayMode(), 327 m_graph[child1].prediction(), 328 m_graph[child2].prediction())); 329 330 blessArrayOperation(child1, 3); 331 332 Node* nodePtr = &m_graph[m_compileIndex]; 333 334 switch (modeForPut(nodePtr->arrayMode())) { 338 335 case Array::Int8Array: 339 336 case Array::Int16Array: … … 369 366 } 370 367 368 NodeIndex checkArray(Array::Mode arrayMode, CodeOrigin codeOrigin, NodeIndex array, bool (*storageCheck)(Array::Mode) = canCSEStorage, bool shouldGenerate = true) 369 { 370 ASSERT(modeIsSpecific(arrayMode)); 371 372 m_graph.ref(array); 373 Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode), array); 374 checkArray.ref(); 375 NodeIndex checkArrayIndex = m_graph.size(); 376 m_graph.append(checkArray); 377 m_insertionSet.append(m_indexInBlock, checkArrayIndex); 378 379 if (!storageCheck(arrayMode)) 380 return NoNode; 381 382 if (shouldGenerate) 383 m_graph.ref(array); 384 Node getIndexedPropertyStorage( 385 GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode), array); 386 if (shouldGenerate) 387 getIndexedPropertyStorage.ref(); 388 NodeIndex getIndexedPropertyStorageIndex = m_graph.size(); 389 m_graph.append(getIndexedPropertyStorage); 390 m_insertionSet.append(m_indexInBlock, getIndexedPropertyStorageIndex); 391 392 return getIndexedPropertyStorageIndex; 393 } 394 395 void blessArrayOperation(Edge base, unsigned storageChildIdx) 396 { 397 if (m_graph.m_fixpointState > BeforeFixpoint) 398 return; 399 400 Node* nodePtr = &m_graph[m_compileIndex]; 401 402 if (nodePtr->arrayMode() == Array::ForceExit) { 403 Node forceExit(ForceOSRExit, nodePtr->codeOrigin); 404 forceExit.ref(); 405 NodeIndex forceExitIndex = m_graph.size(); 406 m_graph.append(forceExit); 407 m_insertionSet.append(m_indexInBlock, forceExitIndex); 408 return; 409 } 410 411 if (!modeIsSpecific(nodePtr->arrayMode())) 412 return; 413 414 NodeIndex storage = checkArray(nodePtr->arrayMode(), nodePtr->codeOrigin, base.index()); 415 if (storage == NoNode) 416 return; 417 418 m_graph.child(m_graph[m_compileIndex], storageChildIdx) = Edge(storage); 419 } 420 371 421 void fixIntEdge(Edge& edge) 372 422 { -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r126387 r126715 40 40 #undef STRINGIZE_DFG_OP_ENUM 41 41 }; 42 43 Graph::Graph(JSGlobalData& globalData, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues) 44 : m_globalData(globalData) 45 , m_codeBlock(codeBlock) 46 , m_profiledBlock(codeBlock->alternative()) 47 , m_hasArguments(false) 48 , m_osrEntryBytecodeIndex(osrEntryBytecodeIndex) 49 , m_mustHandleValues(mustHandleValues) 50 , m_fixpointState(BeforeFixpoint) 51 { 52 ASSERT(m_profiledBlock); 53 } 42 54 43 55 const char *Graph::opName(NodeType op) … … 180 192 else 181 193 hasPrinted = true; 194 if (!m_varArgChildren[childIdx]) 195 continue; 182 196 dataLog("%s@%u%s", 183 197 useKindToString(m_varArgChildren[childIdx].useKind()), … … 393 407 for (unsigned _childIdx = _node.firstChild(); \ 394 408 _childIdx < _node.firstChild() + _node.numChildren(); \ 395 _childIdx++) \ 396 thingToDo(m_varArgChildren[_childIdx]); \ 409 _childIdx++) { \ 410 if (!!m_varArgChildren[_childIdx]) \ 411 thingToDo(m_varArgChildren[_childIdx]); \ 412 } \ 397 413 } else { \ 398 414 if (!_node.child1()) { \ … … 484 500 childIdx < node.firstChild() + node.numChildren(); 485 501 ++childIdx) { 502 if (!m_varArgChildren[childIdx]) 503 continue; 486 504 NodeIndex childNodeIndex = m_varArgChildren[childIdx].index(); 487 505 if (!at(childNodeIndex).ref()) -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r126712 r126715 69 69 class Graph : public Vector<Node, 64> { 70 70 public: 71 Graph(JSGlobalData& globalData, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues) 72 : m_globalData(globalData) 73 , m_codeBlock(codeBlock) 74 , m_profiledBlock(codeBlock->alternative()) 75 , m_hasArguments(false) 76 , m_osrEntryBytecodeIndex(osrEntryBytecodeIndex) 77 , m_mustHandleValues(mustHandleValues) 78 { 79 ASSERT(m_profiledBlock); 80 } 71 Graph(JSGlobalData&, CodeBlock*, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues); 81 72 82 73 using Vector<Node, 64>::operator[]; … … 578 569 for (unsigned childIdx = node.firstChild(); 579 570 childIdx < node.firstChild() + node.numChildren(); 580 childIdx++) 581 vote(m_varArgChildren[childIdx], ballot); 571 childIdx++) { 572 if (!!m_varArgChildren[childIdx]) 573 vote(m_varArgChildren[childIdx], ballot); 574 } 582 575 return; 583 576 } … … 601 594 Node& node = at(nodeIndex); 602 595 if (node.flags() & NodeHasVarArgs) { 603 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); ++childIdx) 604 compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing, node.shouldGenerate()); 596 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); ++childIdx) { 597 if (!!m_varArgChildren[childIdx]) 598 compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing, node.shouldGenerate()); 599 } 605 600 continue; 606 601 } … … 678 673 unsigned m_osrEntryBytecodeIndex; 679 674 Operands<JSValue> m_mustHandleValues; 675 676 OptimizationFixpointState m_fixpointState; 680 677 private: 681 678 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r126387 r126715 744 744 case StringCharAt: 745 745 case StringCharCodeAt: 746 case CheckArray: 747 case ArrayPush: 748 case ArrayPop: 746 749 return true; 747 750 default: … … 756 759 } 757 760 758 voidsetArrayMode(Array::Mode arrayMode)761 bool setArrayMode(Array::Mode arrayMode) 759 762 { 760 763 ASSERT(hasArrayMode()); 764 if (this->arrayMode() == arrayMode) 765 return false; 761 766 m_opInfo = arrayMode; 767 return true; 762 768 } 763 769 -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r126387 r126715 139 139 macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \ 140 140 macro(GetPropertyStorage, NodeResultStorage) \ 141 macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \ 141 macro(CheckArray, NodeMustGenerate) \ 142 macro(GetIndexedPropertyStorage, NodeResultStorage) \ 142 143 macro(GetByOffset, NodeResultJS) \ 143 144 macro(PutByOffset, NodeMustGenerate) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r126494 r126715 576 576 } 577 577 578 EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array) 579 { 580 JSGlobalData* globalData = &exec->globalData(); 581 NativeCallFrameTracer tracer(globalData, exec); 582 583 return JSValue::encode(array->pop(exec)); 584 } 585 578 586 EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument) 579 587 { … … 602 610 JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec); 603 611 return asRegExpObject(base)->test(exec, input); 604 }605 606 EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)607 {608 JSGlobalData* globalData = &exec->globalData();609 NativeCallFrameTracer tracer(globalData, exec);610 611 return JSValue::encode(array->pop(exec));612 612 } 613 613 -
trunk/Source/JavaScriptCore/dfg/DFGPhase.h
r122167 r126715 96 96 } 97 97 98 template<typename PhaseType, typename ArgumentType1>99 bool runPhase(Graph& graph, ArgumentType1 arg1)100 {101 PhaseType phase(graph, arg1);102 return runAndLog(phase);103 }104 105 98 } } // namespace JSC::DFG 106 99 -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r126387 r126715 619 619 case GetMyArgumentByVal: 620 620 case PhantomPutStructure: 621 case PhantomArguments: { 621 case PhantomArguments: 622 case CheckArray: { 622 623 // This node should never be visible at this stage of compilation. It is 623 624 // inserted by fixup(), which follows this phase. … … 704 705 for (unsigned childIdx = node.firstChild(); 705 706 childIdx < node.firstChild() + node.numChildren(); 706 childIdx++) 707 changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue); 707 childIdx++) { 708 if (!!m_graph.m_varArgChildren[childIdx]) 709 changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue); 710 } 708 711 } else { 709 712 if (!node.child1()) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r126387 r126715 296 296 } 297 297 298 const TypedArrayDescriptor* SpeculativeJIT::speculateArray(Array::Mode arrayMode, Edge edge, GPRReg baseReg) 299 { 300 const TypedArrayDescriptor* result = typedArrayDescriptor(arrayMode); 301 302 if (modeAlreadyChecked(m_state.forNode(edge), arrayMode)) 303 return result; 298 void SpeculativeJIT::checkArray(Node& node) 299 { 300 ASSERT(modeIsSpecific(node.arrayMode())); 301 302 SpeculateCellOperand base(this, node.child1()); 303 GPRReg baseReg = base.gpr(); 304 305 const TypedArrayDescriptor* result = typedArrayDescriptor(node.arrayMode()); 306 307 if (modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode())) { 308 noResult(m_compileIndex); 309 return; 310 } 304 311 305 312 const ClassInfo* expectedClassInfo = 0; 306 313 307 switch (arrayMode) { 308 case Array::ForceExit: 309 ASSERT_NOT_REACHED(); 310 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); 311 return result; 314 switch (node.arrayMode()) { 312 315 case Array::String: 313 316 expectedClassInfo = &JSString::s_info; … … 326 329 MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()), 327 330 MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 328 return result; 331 332 noResult(m_compileIndex); 333 return; 329 334 } 330 335 case Array::Arguments: … … 357 362 MacroAssembler::TrustedImmPtr(expectedClassInfo))); 358 363 359 return result;364 noResult(m_compileIndex); 360 365 } 361 366 … … 394 399 { 395 400 if (node.flags() & NodeHasVarArgs) { 396 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) 397 use(m_jit.graph().m_varArgChildren[childIdx]); 401 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) { 402 if (!!m_jit.graph().m_varArgChildren[childIdx]) 403 use(m_jit.graph().m_varArgChildren[childIdx]); 404 } 398 405 } else { 399 406 Edge child1 = node.child1(); … … 2147 2154 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySignedness signedness, TypedArrayRounding rounding) 2148 2155 { 2156 StorageOperand storage(this, m_jit.graph().varArgChild(node, 3)); 2157 GPRReg storageReg = storage.gpr(); 2158 2149 2159 Edge valueUse = m_jit.graph().varArgChild(node, 2); 2150 2160 … … 2214 2224 ASSERT_UNUSED(valueGPR, valueGPR != property); 2215 2225 ASSERT(valueGPR != base); 2216 GPRTemporary storage(this);2217 GPRReg storageReg = storage.gpr();2218 2226 ASSERT(valueGPR != storageReg); 2219 m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);2220 2227 MacroAssembler::Jump outOfBounds; 2221 2228 if (node.op() == PutByVal) … … 2279 2286 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize) 2280 2287 { 2288 StorageOperand storage(this, m_jit.graph().varArgChild(node, 3)); 2289 GPRReg storageReg = storage.gpr(); 2290 2281 2291 Edge baseUse = m_jit.graph().varArgChild(node, 0); 2282 2292 Edge valueUse = m_jit.graph().varArgChild(node, 2); … … 2288 2298 GPRTemporary result(this); 2289 2299 2290 GPRTemporary storage(this);2291 GPRReg storageReg = storage.gpr();2292 2293 m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);2294 2300 MacroAssembler::Jump outOfBounds; 2295 2301 if (node.op() == PutByVal) … … 3110 3116 GPRReg storageReg = storage.gpr(); 3111 3117 3112 const TypedArrayDescriptor* descriptor = 3113 speculateArray(node.arrayMode(), node.child1(), baseReg); 3118 const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode()); 3114 3119 3115 3120 switch (node.arrayMode()) { … … 3253 3258 void SpeculativeJIT::compileGetArrayLength(Node& node) 3254 3259 { 3255 SpeculateCellOperand base(this, node.child1()); 3256 GPRTemporary result(this); 3257 3258 GPRReg baseGPR = base.gpr(); 3259 GPRReg resultGPR = result.gpr(); 3260 3261 const TypedArrayDescriptor* descriptor = 3262 speculateArray(node.arrayMode(), node.child1(), baseGPR); 3260 const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode()); 3263 3261 3264 3262 switch (node.arrayMode()) { 3265 3263 case Array::JSArray: 3266 case Array::JSArrayOutOfBounds: 3267 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR); 3268 m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR); 3264 case Array::JSArrayOutOfBounds: { 3265 StorageOperand storage(this, node.child2()); 3266 GPRTemporary result(this, storage); 3267 GPRReg storageReg = storage.gpr(); 3268 GPRReg resultReg = result.gpr(); 3269 m_jit.load32(MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultReg); 3269 3270 3270 speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, result GPR, MacroAssembler::TrustedImm32(0)));3271 speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, MacroAssembler::TrustedImm32(0))); 3271 3272 3272 integerResult(result GPR, m_compileIndex);3273 integerResult(resultReg, m_compileIndex); 3273 3274 break; 3274 case Array::String: 3275 } 3276 case Array::String: { 3277 SpeculateCellOperand base(this, node.child1()); 3278 GPRTemporary result(this, base); 3279 GPRReg baseGPR = base.gpr(); 3280 GPRReg resultGPR = result.gpr(); 3275 3281 m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR); 3276 3282 integerResult(resultGPR, m_compileIndex); 3277 3283 break; 3278 case Array::Arguments: 3284 } 3285 case Array::Arguments: { 3279 3286 compileGetArgumentsLength(node); 3280 3287 break; 3288 } 3281 3289 default: 3290 SpeculateCellOperand base(this, node.child1()); 3291 GPRTemporary result(this, base); 3292 GPRReg baseGPR = base.gpr(); 3293 GPRReg resultGPR = result.gpr(); 3282 3294 ASSERT(descriptor); 3283 3295 m_jit.load32(MacroAssembler::Address(baseGPR, descriptor->m_lengthOffset), resultGPR); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r126387 r126715 2198 2198 const TypedArrayDescriptor* typedArrayDescriptor(Array::Mode); 2199 2199 2200 const TypedArrayDescriptor* speculateArray(Array::Mode, Edge baseEdge, GPRReg baseReg);2200 void checkArray(Node&); 2201 2201 2202 2202 template<bool strict> -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r126695 r126715 2374 2374 break; 2375 2375 } 2376 2377 case CheckArray: { 2378 checkArray(node); 2379 break; 2380 } 2376 2381 2377 2382 case GetByVal: { … … 2471 2476 Edge child2 = m_jit.graph().varArgChild(node, 1); 2472 2477 Edge child3 = m_jit.graph().varArgChild(node, 2); 2478 Edge child4 = m_jit.graph().varArgChild(node, 3); 2473 2479 2474 2480 Array::Mode arrayMode = modeForPut(node.arrayMode()); … … 2514 2520 GPRReg propertyReg = property.gpr(); 2515 2521 2516 speculateArray(arrayMode, child1, baseReg);2517 2518 2522 switch (arrayMode) { 2519 2523 case Array::JSArray: … … 2532 2536 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg); 2533 2537 } 2538 2539 StorageOperand storage(this, child4); 2540 GPRReg storageReg = storage.gpr(); 2534 2541 2535 2542 if (node.op() == PutByValAlias) { 2536 // Get the array storage.2537 GPRTemporary storage(this);2538 GPRReg storageReg = storage.gpr();2539 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);2540 2541 2543 // Store the value to the array. 2542 2544 GPRReg propertyReg = property.gpr(); … … 2555 2557 property.use(); 2556 2558 value.use(); 2557 2558 // Get the array storage. 2559 GPRTemporary storage(this); 2560 GPRReg storageReg = storage.gpr(); 2561 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); 2562 2559 storage.use(); 2560 2563 2561 // Check if we're writing to a hole; if so increment m_numValuesInVector. 2564 2562 MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); … … 2689 2687 2690 2688 case ArrayPush: { 2689 ASSERT(modeIsJSArray(node.arrayMode())); 2690 2691 2691 SpeculateCellOperand base(this, node.child1()); 2692 2692 JSValueOperand value(this, node.child2()); … … 2698 2698 GPRReg storageLengthGPR = storageLength.gpr(); 2699 2699 2700 {2700 if (Heap::isWriteBarrierEnabled()) { 2701 2701 GPRTemporary scratch(this); 2702 2702 writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); 2703 2703 } 2704 2704 2705 speculateArray(Array::JSArray, node.child1(), baseGPR); 2706 2707 GPRTemporary storage(this); 2705 StorageOperand storage(this, node.child3()); 2708 2706 GPRReg storageGPR = storage.gpr(); 2709 2707 2710 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);2711 2708 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); 2712 2709 … … 2731 2728 2732 2729 case ArrayPop: { 2730 ASSERT(modeIsJSArray(node.arrayMode())); 2731 2733 2732 SpeculateCellOperand base(this, node.child1()); 2733 StorageOperand storage(this, node.child2()); 2734 2734 GPRTemporary valueTag(this); 2735 2735 GPRTemporary valuePayload(this); 2736 GPRTemporary storage(this);2737 2736 GPRTemporary storageLength(this); 2738 2737 … … 2743 2742 GPRReg storageLengthGPR = storageLength.gpr(); 2744 2743 2745 speculateArray(Array::JSArray, node.child1(), baseGPR);2746 2747 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);2748 2744 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); 2749 2745 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r126695 r126715 2407 2407 break; 2408 2408 } 2409 2410 case CheckArray: { 2411 checkArray(node); 2412 break; 2413 } 2409 2414 2410 2415 case GetByVal: { … … 2498 2503 Edge child2 = m_jit.graph().varArgChild(node, 1); 2499 2504 Edge child3 = m_jit.graph().varArgChild(node, 2); 2505 Edge child4 = m_jit.graph().varArgChild(node, 3); 2500 2506 2501 2507 Array::Mode arrayMode = modeForPut(node.arrayMode()); … … 2539 2545 GPRReg propertyReg = property.gpr(); 2540 2546 2541 speculateArray(arrayMode, child1, baseReg);2542 2543 2547 switch (arrayMode) { 2544 2548 case Array::JSArray: 2545 2549 case Array::JSArrayOutOfBounds: { 2546 2550 JSValueOperand value(this, child3); 2547 GPRTemporary scratch(this);2548 2551 2549 2552 // Map base, property & value into registers, allocate a scratch register. 2550 2553 GPRReg valueReg = value.gpr(); 2551 GPRReg scratchReg = scratch.gpr();2552 2554 2553 2555 if (!m_compileOkay) 2554 2556 return; 2555 2557 2556 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg); 2558 if (Heap::isWriteBarrierEnabled()) { 2559 GPRTemporary scratch(this); 2560 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr()); 2561 } 2562 2563 StorageOperand storage(this, child4); 2564 GPRReg storageReg = storage.gpr(); 2557 2565 2558 2566 if (node.op() == PutByValAlias) { 2559 GPRReg storageReg = scratchReg;2560 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);2561 2562 2567 // Store the value to the array. 2563 2568 GPRReg propertyReg = property.gpr(); … … 2576 2581 property.use(); 2577 2582 value.use(); 2578 2579 // Get the array storage. 2580 GPRReg storageReg = scratchReg; 2581 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); 2582 2583 storage.use(); 2584 2583 2585 // Check if we're writing to a hole; if so increment m_numValuesInVector. 2584 2586 MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); … … 2748 2750 2749 2751 case ArrayPush: { 2752 ASSERT(modeIsJSArray(node.arrayMode())); 2753 2750 2754 SpeculateCellOperand base(this, node.child1()); 2751 2755 JSValueOperand value(this, node.child2()); 2752 GPRTemporary storage(this);2753 2756 GPRTemporary storageLength(this); 2754 2757 2755 2758 GPRReg baseGPR = base.gpr(); 2756 2759 GPRReg valueGPR = value.gpr(); 2760 GPRReg storageLengthGPR = storageLength.gpr(); 2761 2762 if (Heap::isWriteBarrierEnabled()) { 2763 GPRTemporary scratch(this); 2764 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); 2765 } 2766 2767 StorageOperand storage(this, node.child3()); 2757 2768 GPRReg storageGPR = storage.gpr(); 2758 GPRReg storageLengthGPR = storageLength.gpr(); 2759 2760 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR); 2761 2762 speculateArray(Array::JSArray, node.child1(), baseGPR); 2763 2764 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); 2769 2765 2770 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); 2766 2771 … … 2787 2792 2788 2793 case ArrayPop: { 2794 ASSERT(modeIsJSArray(node.arrayMode())); 2795 2789 2796 SpeculateCellOperand base(this, node.child1()); 2797 StorageOperand storage(this, node.child2()); 2790 2798 GPRTemporary value(this); 2791 GPRTemporary storage(this);2792 2799 GPRTemporary storageLength(this); 2793 2800 2794 2801 GPRReg baseGPR = base.gpr(); 2802 GPRReg storageGPR = storage.gpr(); 2795 2803 GPRReg valueGPR = value.gpr(); 2796 GPRReg storageGPR = storage.gpr();2797 2804 GPRReg storageLengthGPR = storageLength.gpr(); 2798 2805 2799 speculateArray(Array::JSArray, node.child1(), baseGPR);2800 2801 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);2802 2806 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); 2803 2807 -
trunk/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
r126387 r126715 100 100 case PutByValAlias: 101 101 case GetArrayLength: 102 case CheckArray: 103 case GetIndexedPropertyStorage: 102 104 case Phantom: 103 105 // Don't count these uses.
Note: See TracChangeset
for help on using the changeset viewer.