Changeset 163027 in webkit for trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
- Timestamp:
- Jan 29, 2014, 11:18:54 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r162777 r163027 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 #include "DFGInPlaceAbstractState.h" 34 34 #include "FTLAbstractHeapRepository.h" 35 #include "FTLAvailableRecovery.h" 35 36 #include "FTLForOSREntryJITCode.h" 36 37 #include "FTLFormattedValue.h" … … 52 53 static std::atomic<int> compileCounter; 53 54 55 // FIXME: Get rid of this and introduce a real stack check. 56 // https://bugs.webkit.org/show_bug.cgi?id=125650 57 static uintptr_t stackLimit; 58 54 59 // Using this instead of typeCheck() helps to reduce the load on LLVM, by creating 55 60 // significantly less dead code. … … 93 98 94 99 m_ftlState.function = addFunction( 95 m_ftlState.module, name.data(), functionType(m_out.int64 , m_out.intPtr));100 m_ftlState.module, name.data(), functionType(m_out.int64)); 96 101 setFunctionCallingConv(m_ftlState.function, LLVMCCallConv); 102 if (isX86() && Options::llvmDisallowAVX()) { 103 // AVX makes V8/raytrace 80% slower. It makes Kraken/audio-oscillator 4.5x 104 // slower. It should be disabled. 105 addTargetDependentFunctionAttr(m_ftlState.function, "target-features", "-avx"); 106 } 97 107 98 108 m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps); 99 109 100 m_prologue = appendBasicBlock(m_ftlState.context, m_ftlState.function); 101 m_out.appendTo(m_prologue); 102 createPhiVariables(); 103 104 m_callFrame = m_out.param(0); 105 m_tagTypeNumber = m_out.constInt64(TagTypeNumber); 106 m_tagMask = m_out.constInt64(TagMask); 107 110 m_prologue = FTL_NEW_BLOCK(m_out, ("Prologue")); 111 LBasicBlock stackOverflow = FTL_NEW_BLOCK(m_out, ("Stack overflow")); 112 m_handleExceptions = FTL_NEW_BLOCK(m_out, ("Handle Exceptions")); 113 108 114 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { 109 115 m_highBlock = m_graph.block(blockIndex); … … 113 119 } 114 120 115 m_out.appendTo(m_prologue); 116 m_out.jump(lowBlock(m_graph.block(0))); 121 m_out.appendTo(m_prologue, stackOverflow); 122 createPhiVariables(); 123 LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal)); 124 m_captured = m_out.add( 125 m_out.ptrToInt(capturedAlloca, m_out.intPtr), 126 m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register))); 127 128 // We should not create any alloca's after this point, since they will cease to 129 // be mem2reg candidates. 130 131 m_ftlState.capturedStackmapID = m_stackmapIDs++; 132 m_out.call( 133 m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID), 134 m_out.int32Zero, capturedAlloca); 135 136 m_callFrame = m_out.ptrToInt( 137 m_out.call(m_out.frameAddressIntrinsic(), m_out.int32Zero), m_out.intPtr); 138 m_tagTypeNumber = m_out.constInt64(TagTypeNumber); 139 m_tagMask = m_out.constInt64(TagMask); 140 141 m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(JSStack::CodeBlock)); 142 m_out.branch( 143 m_out.below(m_callFrame, m_out.loadPtr(m_out.absolute(&stackLimit))), 144 stackOverflow, lowBlock(m_graph.block(0))); 145 146 m_out.appendTo(stackOverflow, m_handleExceptions); 147 // FIXME: Do a real stack check and throw the exception appropriately. 148 // https://bugs.webkit.org/show_bug.cgi?id=125650 149 m_out.crash(); 150 151 m_out.appendTo(m_handleExceptions, lowBlock(m_graph.block(0))); 152 m_ftlState.handleExceptionStackmapID = m_stackmapIDs++; 153 m_out.call( 154 m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleExceptionStackmapID), 155 m_out.constInt32(MacroAssembler::maxJumpReplacementSize())); 156 m_out.unreachable(); 117 157 118 158 Vector<BasicBlock*> depthFirst; … … 227 267 dataLog("Lowering ", m_node, "\n"); 228 268 269 m_availableRecoveries.resize(0); 270 229 271 bool shouldExecuteEffects = m_interpreter.startExecuting(m_node); 230 272 … … 266 308 break; 267 309 case ArithAdd: 268 compileAddSub();269 break;270 310 case ArithSub: 271 compileA ddSub();311 compileArithAddOrSub(); 272 312 break; 273 313 case ArithMul: … … 275 315 break; 276 316 case ArithDiv: 277 compileArithDiv Mod();317 compileArithDiv(); 278 318 break; 279 319 case ArithMod: 280 compileArith DivMod();320 compileArithMod(); 281 321 break; 282 322 case ArithMin: … … 287 327 compileArithAbs(); 288 328 break; 329 case ArithSin: 330 compileArithSin(); 331 break; 332 case ArithCos: 333 compileArithCos(); 334 break; 335 case ArithSqrt: 336 compileArithSqrt(); 337 break; 289 338 case ArithNegate: 290 339 compileArithNegate(); … … 323 372 compileCheckFunction(); 324 373 break; 374 case CheckExecutable: 375 compileCheckExecutable(); 376 break; 325 377 case ArrayifyToStructure: 326 378 compileArrayifyToStructure(); … … 335 387 compileGetById(); 336 388 break; 389 case PutByIdDirect: 337 390 case PutById: 338 391 compilePutById(); … … 373 426 compileNewArrayBuffer(); 374 427 break; 428 case NewArrayWithSize: 429 compileNewArrayWithSize(); 430 break; 375 431 case AllocatePropertyStorage: 376 432 compileAllocatePropertyStorage(); 377 433 break; 434 case ToString: 435 compileToString(); 436 break; 437 case MakeRope: 438 compileMakeRope(); 439 break; 378 440 case StringCharAt: 379 441 compileStringCharAt(); … … 396 458 case NotifyWrite: 397 459 compileNotifyWrite(); 460 break; 461 case GetCallee: 462 compileGetCallee(); 463 break; 464 case GetScope: 465 compileGetScope(); 398 466 break; 399 467 case GetMyScope: … … 466 534 case Int52ToValue: 467 535 compileInt52ToValue(); 536 break; 537 case CheckArgumentsNotCreated: 538 compileCheckArgumentsNotCreated(); 539 break; 540 case CountExecution: 541 compileCountExecution(); 468 542 break; 469 543 case StoreBarrier: … … 483 557 case FunctionReentryWatchpoint: 484 558 case TypedArrayWatchpoint: 559 case AllocationProfileWatchpoint: 485 560 break; 486 561 default: … … 816 891 } 817 892 818 void compileA ddSub()893 void compileArithAddOrSub() 819 894 { 820 895 bool isSub = m_node->op() == ArithSub; … … 823 898 LValue left = lowInt32(m_node->child1()); 824 899 LValue right = lowInt32(m_node->child2()); 825 LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);826 900 827 901 if (!shouldCheckOverflow(m_node->arithMode())) { 828 setInt32( result);902 setInt32(isSub ? m_out.sub(left, right) : m_out.add(left, right)); 829 903 break; 830 904 } 831 905 832 LValue overflow = isSub ? m_out.subWithOverflow32(left, right) : m_out.addWithOverflow32(left, right); 833 834 speculate(Overflow, noValue(), 0, m_out.extractValue(overflow, 1)); 835 setInt32(result); 906 LValue result; 907 if (!isSub) { 908 result = m_out.addWithOverflow32(left, right); 909 910 if (doesKill(m_node->child2())) { 911 addAvailableRecovery( 912 m_node->child2(), SubRecovery, 913 m_out.extractValue(result, 0), left, ValueFormatInt32); 914 } else if (doesKill(m_node->child1())) { 915 addAvailableRecovery( 916 m_node->child1(), SubRecovery, 917 m_out.extractValue(result, 0), right, ValueFormatInt32); 918 } 919 } else { 920 result = m_out.subWithOverflow32(left, right); 921 922 if (doesKill(m_node->child2())) { 923 // result = left - right 924 // result - left = -right 925 // right = left - result 926 addAvailableRecovery( 927 m_node->child2(), SubRecovery, 928 left, m_out.extractValue(result, 0), ValueFormatInt32); 929 } else if (doesKill(m_node->child1())) { 930 // result = left - right 931 // result + right = left 932 addAvailableRecovery( 933 m_node->child1(), AddRecovery, 934 m_out.extractValue(result, 0), right, ValueFormatInt32); 935 } 936 } 937 938 speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); 939 setInt32(m_out.extractValue(result, 0)); 836 940 break; 837 941 } … … 849 953 LValue left = lowInt52(m_node->child1()); 850 954 LValue right = lowInt52(m_node->child2()); 851 LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right); 852 853 LValue overflow = isSub ? m_out.subWithOverflow64(left, right) : m_out.addWithOverflow64(left, right); 854 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflow, 1)); 855 setInt52(result); 955 956 LValue result; 957 if (!isSub) { 958 result = m_out.addWithOverflow64(left, right); 959 960 if (doesKill(m_node->child2())) { 961 addAvailableRecovery( 962 m_node->child2(), SubRecovery, 963 m_out.extractValue(result, 0), left, ValueFormatInt52); 964 } else if (doesKill(m_node->child1())) { 965 addAvailableRecovery( 966 m_node->child1(), SubRecovery, 967 m_out.extractValue(result, 0), right, ValueFormatInt52); 968 } 969 } else { 970 result = m_out.subWithOverflow64(left, right); 971 972 if (doesKill(m_node->child2())) { 973 // result = left - right 974 // result - left = -right 975 // right = left - result 976 addAvailableRecovery( 977 m_node->child2(), SubRecovery, 978 left, m_out.extractValue(result, 0), ValueFormatInt52); 979 } else if (doesKill(m_node->child1())) { 980 // result = left - right 981 // result + right = left 982 addAvailableRecovery( 983 m_node->child1(), AddRecovery, 984 m_out.extractValue(result, 0), right, ValueFormatInt52); 985 } 986 } 987 988 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1)); 989 setInt52(m_out.extractValue(result, 0)); 856 990 break; 857 991 } … … 877 1011 LValue left = lowInt32(m_node->child1()); 878 1012 LValue right = lowInt32(m_node->child2()); 879 LValue result = m_out.mul(left, right); 880 881 if (shouldCheckOverflow(m_node->arithMode())) { 1013 1014 LValue result; 1015 1016 if (!shouldCheckOverflow(m_node->arithMode())) 1017 result = m_out.mul(left, right); 1018 else { 882 1019 LValue overflowResult = m_out.mulWithOverflow32(left, right); 883 1020 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 1021 result = m_out.extractValue(overflowResult, 0); 884 1022 } 885 1023 … … 905 1043 LValue left = lowWhicheverInt52(m_node->child1(), kind); 906 1044 LValue right = lowInt52(m_node->child2(), opposite(kind)); 907 LValue result = m_out.mul(left, right);908 909 1045 910 1046 LValue overflowResult = m_out.mulWithOverflow64(left, right); 911 1047 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 1048 LValue result = m_out.extractValue(overflowResult, 0); 912 1049 913 1050 if (shouldCheckNegativeZero(m_node->arithMode())) { … … 940 1077 } 941 1078 942 void compileArithDiv Mod()1079 void compileArithDiv() 943 1080 { 944 1081 switch (m_node->binaryUseKind()) { … … 947 1084 LValue denominator = lowInt32(m_node->child2()); 948 1085 949 LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv Modunsafe denominator"));950 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv Modcontinuation"));951 LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv Moddone"));1086 LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv unsafe denominator")); 1087 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv continuation")); 1088 LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv done")); 952 1089 953 1090 Vector<ValueFromBlock, 3> results; … … 992 1129 993 1130 if (shouldCheckNegativeZero(m_node->arithMode())) { 994 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv Modzero numerator"));995 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv Modnumerator continuation"));1131 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv zero numerator")); 1132 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv numerator continuation")); 996 1133 997 1134 m_out.branch(m_out.isZero32(numerator), zeroNumerator, numeratorContinuation); … … 1007 1144 } 1008 1145 1009 LValue divModResult = m_node->op() == ArithDiv 1010 ? m_out.div(numerator, denominator) 1011 : m_out.rem(numerator, denominator); 1146 LValue result = m_out.div(numerator, denominator); 1012 1147 1013 1148 if (shouldCheckOverflow(m_node->arithMode())) { 1014 1149 speculate( 1015 1150 Overflow, noValue(), 0, 1016 m_out.notEqual(m_out.mul( divModResult, denominator), numerator));1151 m_out.notEqual(m_out.mul(result, denominator), numerator)); 1017 1152 } 1018 1153 1019 results.append(m_out.anchor( divModResult));1154 results.append(m_out.anchor(result)); 1020 1155 m_out.jump(done); 1021 1156 … … 1027 1162 1028 1163 case NumberUse: { 1029 LValue C1 = lowDouble(m_node->child1()); 1030 LValue C2 = lowDouble(m_node->child2()); 1031 setDouble(m_node->op() == ArithDiv ? m_out.doubleDiv(C1, C2) : m_out.doubleRem(C1, C2)); 1164 setDouble(m_out.doubleDiv( 1165 lowDouble(m_node->child1()), lowDouble(m_node->child2()))); 1032 1166 break; 1033 1167 } … … 1039 1173 } 1040 1174 1175 void compileArithMod() 1176 { 1177 switch (m_node->binaryUseKind()) { 1178 case Int32Use: { 1179 LValue numerator = lowInt32(m_node->child1()); 1180 LValue denominator = lowInt32(m_node->child2()); 1181 1182 LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator")); 1183 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation")); 1184 LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done")); 1185 1186 Vector<ValueFromBlock, 3> results; 1187 1188 LValue adjustedDenominator = m_out.add(denominator, m_out.int32One); 1189 1190 m_out.branch(m_out.above(adjustedDenominator, m_out.int32One), continuation, unsafeDenominator); 1191 1192 LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation); 1193 1194 LValue neg2ToThe31 = m_out.constInt32(-2147483647-1); 1195 1196 // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a 1197 // separate case for that. But it probably doesn't matter so much. 1198 if (shouldCheckOverflow(m_node->arithMode())) { 1199 LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31)); 1200 speculate(Overflow, noValue(), 0, cond); 1201 m_out.jump(continuation); 1202 } else { 1203 // This is the case where we convert the result to an int after we're done. So, 1204 // if the denominator is zero, then the result should be result should be zero. 1205 // If the denominator is not zero (i.e. it's -1 because we're guarded by the 1206 // check above) and the numerator is -2^31 then the result should be -2^31. 1207 1208 LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero")); 1209 LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero")); 1210 LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1")); 1211 1212 m_out.branch(m_out.isZero32(denominator), modByZero, notModByZero); 1213 1214 m_out.appendTo(modByZero, notModByZero); 1215 results.append(m_out.anchor(m_out.int32Zero)); 1216 m_out.jump(done); 1217 1218 m_out.appendTo(notModByZero, neg2ToThe31ByNeg1); 1219 m_out.branch(m_out.equal(numerator, neg2ToThe31), neg2ToThe31ByNeg1, continuation); 1220 1221 m_out.appendTo(neg2ToThe31ByNeg1, continuation); 1222 results.append(m_out.anchor(m_out.int32Zero)); 1223 m_out.jump(done); 1224 } 1225 1226 m_out.appendTo(continuation, done); 1227 1228 LValue remainder = m_out.rem(numerator, denominator); 1229 1230 if (shouldCheckNegativeZero(m_node->arithMode())) { 1231 LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator")); 1232 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation")); 1233 1234 m_out.branch( 1235 m_out.lessThan(numerator, m_out.int32Zero), 1236 negativeNumerator, numeratorContinuation); 1237 1238 LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation); 1239 1240 speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder)); 1241 1242 m_out.jump(numeratorContinuation); 1243 1244 m_out.appendTo(numeratorContinuation, innerLastNext); 1245 } 1246 1247 results.append(m_out.anchor(remainder)); 1248 m_out.jump(done); 1249 1250 m_out.appendTo(done, lastNext); 1251 1252 setInt32(m_out.phi(m_out.int32, results)); 1253 break; 1254 } 1255 1256 case NumberUse: { 1257 setDouble( 1258 m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); 1259 break; 1260 } 1261 1262 default: 1263 RELEASE_ASSERT_NOT_REACHED(); 1264 break; 1265 } 1266 } 1267 1041 1268 void compileArithMinOrMax() 1042 1269 { … … 1115 1342 } 1116 1343 } 1344 1345 void compileArithSin() { setDouble(m_out.doubleSin(lowDouble(m_node->child1()))); } 1346 1347 void compileArithCos() { setDouble(m_out.doubleCos(lowDouble(m_node->child1()))); } 1348 1349 void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); } 1117 1350 1118 1351 void compileArithNegate() … … 1122 1355 LValue value = lowInt32(m_node->child1()); 1123 1356 1124 LValue result = m_out.neg(value); 1125 if (shouldCheckOverflow(m_node->arithMode())) { 1126 if (!shouldCheckNegativeZero(m_node->arithMode())) { 1127 // We don't have a negate-with-overflow intrinsic. Hopefully this 1128 // does the trick, though. 1129 LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value); 1130 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 1131 } else 1132 speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff))); 1133 1357 LValue result; 1358 if (!shouldCheckOverflow(m_node->arithMode())) 1359 result = m_out.neg(value); 1360 else if (!shouldCheckNegativeZero(m_node->arithMode())) { 1361 // We don't have a negate-with-overflow intrinsic. Hopefully this 1362 // does the trick, though. 1363 LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value); 1364 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 1365 result = m_out.extractValue(overflowResult, 0); 1366 } else { 1367 speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff))); 1368 result = m_out.neg(value); 1134 1369 } 1135 1370 … … 1152 1387 LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value); 1153 1388 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 1154 LValue result = m_out. neg(value);1389 LValue result = m_out.extractValue(overflowResult, 0); 1155 1390 speculate(NegativeZero, noValue(), 0, m_out.isZero64(result)); 1156 1391 setInt52(result); … … 1274 1509 BadFunction, jsValueValue(cell), m_node->child1().node(), 1275 1510 m_out.notEqual(cell, weakPointer(m_node->function()))); 1511 } 1512 1513 void compileCheckExecutable() 1514 { 1515 LValue cell = lowCell(m_node->child1()); 1516 1517 speculate( 1518 BadExecutable, jsValueValue(cell), m_node->child1().node(), 1519 m_out.notEqual( 1520 m_out.loadPtr(cell, m_heaps.JSFunction_executable), 1521 weakPointer(m_node->executable()))); 1276 1522 } 1277 1523 … … 1371 1617 LValue call = m_out.call( 1372 1618 m_out.patchpointInt64Intrinsic(), 1373 m_out.constInt 32(stackmapID), m_out.constInt32(sizeOfGetById()),1374 constNull(m_out.ref8), m_out.constInt32( 2), m_callFrame, base);1619 m_out.constInt64(stackmapID), m_out.constInt32(sizeOfGetById()), 1620 constNull(m_out.ref8), m_out.constInt32(1), base); 1375 1621 setInstructionCallingConvention(call, LLVMAnyRegCallConv); 1376 1622 setJSValue(call); … … 1396 1642 LValue call = m_out.call( 1397 1643 m_out.patchpointVoidIntrinsic(), 1398 m_out.constInt 32(stackmapID), m_out.constInt32(sizeOfPutById()),1399 constNull(m_out.ref8), m_out.constInt32( 3), m_callFrame, base, value);1644 m_out.constInt64(stackmapID), m_out.constInt32(sizeOfPutById()), 1645 constNull(m_out.ref8), m_out.constInt32(2), base, value); 1400 1646 setInstructionCallingConvention(call, LLVMAnyRegCallConv); 1401 1647 … … 1464 1710 case Array::Double: 1465 1711 case Array::Contiguous: { 1466 setInt32(m_out.load32 (lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));1712 setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength)); 1467 1713 return; 1468 1714 } … … 1470 1716 case Array::String: { 1471 1717 LValue string = lowCell(m_node->child1()); 1472 setInt32(m_out.load32 (string, m_heaps.JSString_length));1718 setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length)); 1473 1719 return; 1474 1720 } … … 1477 1723 if (isTypedView(m_node->arrayMode().typedArrayType())) { 1478 1724 setInt32( 1479 m_out.load32 (lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));1725 m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); 1480 1726 return; 1481 1727 } … … 1519 1765 m_out.branch( 1520 1766 m_out.aboveOrEqual( 1521 index, m_out.load32 (storage, m_heaps.Butterfly_publicLength)),1767 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)), 1522 1768 slowCase, fastCase); 1523 1769 … … 1566 1812 m_out.branch( 1567 1813 m_out.aboveOrEqual( 1568 index, m_out.load32 (storage, m_heaps.Butterfly_publicLength)),1814 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)), 1569 1815 slowCase, inBounds); 1570 1816 … … 1688 1934 Edge child3 = m_graph.varArgChild(m_node, 2); 1689 1935 Edge child4 = m_graph.varArgChild(m_node, 3); 1936 Edge child5 = m_graph.varArgChild(m_node, 4); 1690 1937 1691 1938 switch (m_node->arrayMode().type()) { … … 1801 2048 m_out.zeroExt(index, m_out.intPtr), 1802 2049 m_out.constIntPtr(logElementSize(type))))); 2050 2051 LType refType; 2052 LValue valueToStore; 1803 2053 1804 2054 if (isInt(type)) { … … 1877 2127 switch (elementSize(type)) { 1878 2128 case 1: 1879 m_out.store8(m_out.intCast(intValue, m_out.int8), pointer); 2129 valueToStore = m_out.intCast(intValue, m_out.int8); 2130 refType = m_out.ref8; 1880 2131 break; 1881 2132 case 2: 1882 m_out.store16(m_out.intCast(intValue, m_out.int16), pointer); 2133 valueToStore = m_out.intCast(intValue, m_out.int16); 2134 refType = m_out.ref16; 1883 2135 break; 1884 2136 case 4: 1885 m_out.store32(intValue, pointer); 2137 valueToStore = intValue; 2138 refType = m_out.ref32; 1886 2139 break; 1887 2140 default: 1888 2141 RELEASE_ASSERT_NOT_REACHED(); 1889 2142 } 2143 } else /* !isInt(type) */ { 2144 LValue value = lowDouble(child3); 2145 switch (type) { 2146 case TypeFloat32: 2147 valueToStore = m_out.fpCast(value, m_out.floatType); 2148 refType = m_out.refFloat; 2149 break; 2150 case TypeFloat64: 2151 valueToStore = value; 2152 refType = m_out.refDouble; 2153 break; 2154 default: 2155 RELEASE_ASSERT_NOT_REACHED(); 2156 } 2157 } 2158 2159 if (m_node->arrayMode().isInBounds()) 2160 m_out.store(valueToStore, pointer, refType); 2161 else { 2162 LBasicBlock isInBounds = FTL_NEW_BLOCK(m_out, ("PutByVal typed array in bounds case")); 2163 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal typed array continuation")); 1890 2164 1891 return; 2165 m_out.branch( 2166 m_out.aboveOrEqual(index, lowInt32(child5)), 2167 continuation, isInBounds); 2168 2169 LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation); 2170 m_out.store(valueToStore, pointer, refType); 2171 m_out.jump(continuation); 2172 2173 m_out.appendTo(continuation, lastNext); 1892 2174 } 1893 2175 1894 ASSERT(isFloat(type));1895 1896 LValue value = lowDouble(child3);1897 switch (type) {1898 case TypeFloat32:1899 m_out.storeFloat(m_out.fpCast(value, m_out.floatType), pointer);1900 break;1901 case TypeFloat64:1902 m_out.storeDouble(value, pointer);1903 break;1904 default:1905 RELEASE_ASSERT_NOT_REACHED();1906 }1907 2176 return; 1908 2177 } … … 2061 2330 } 2062 2331 2332 void compileNewArrayWithSize() 2333 { 2334 LValue publicLength = lowInt32(m_node->child1()); 2335 2336 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->codeOrigin); 2337 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation( 2338 m_node->indexingType()); 2339 2340 if (!globalObject->isHavingABadTime() && !hasArrayStorage(m_node->indexingType())) { 2341 ASSERT( 2342 hasUndecided(structure->indexingType()) 2343 || hasInt32(structure->indexingType()) 2344 || hasDouble(structure->indexingType()) 2345 || hasContiguous(structure->indexingType())); 2346 2347 LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fast case")); 2348 LBasicBlock largeCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize large case")); 2349 LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fail case")); 2350 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize slow case")); 2351 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize continuation")); 2352 2353 m_out.branch( 2354 m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)), 2355 largeCase, fastCase); 2356 2357 LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase); 2358 2359 // We don't round up to BASE_VECTOR_LEN for new Array(blah). 2360 LValue vectorLength = publicLength; 2361 2362 LValue payloadSize = 2363 m_out.shl(m_out.zeroExt(vectorLength, m_out.intPtr), m_out.constIntPtr(3)); 2364 2365 LValue butterflySize = m_out.add( 2366 payloadSize, m_out.constIntPtr(sizeof(IndexingHeader))); 2367 2368 LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase); 2369 2370 LValue butterfly = m_out.sub(endOfStorage, payloadSize); 2371 2372 LValue object = allocateObject<JSArray>( 2373 m_out.constIntPtr(structure), butterfly, failCase); 2374 2375 m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength); 2376 m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength); 2377 2378 if (hasDouble(m_node->indexingType())) { 2379 LBasicBlock initLoop = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init loop")); 2380 LBasicBlock initDone = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init done")); 2381 2382 ValueFromBlock originalIndex = m_out.anchor(vectorLength); 2383 ValueFromBlock originalPointer = m_out.anchor(butterfly); 2384 m_out.branch(m_out.notZero32(vectorLength), initLoop, initDone); 2385 2386 LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone); 2387 LValue index = m_out.phi(m_out.int32, originalIndex); 2388 LValue pointer = m_out.phi(m_out.intPtr, originalPointer); 2389 2390 m_out.store64( 2391 m_out.constInt64(bitwise_cast<int64_t>(QNaN)), 2392 TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer)); 2393 2394 LValue nextIndex = m_out.sub(index, m_out.int32One); 2395 addIncoming(index, m_out.anchor(nextIndex)); 2396 addIncoming(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight))); 2397 m_out.branch(m_out.notZero32(nextIndex), initLoop, initDone); 2398 2399 m_out.appendTo(initDone, initLastNext); 2400 } 2401 2402 ValueFromBlock fastResult = m_out.anchor(object); 2403 m_out.jump(continuation); 2404 2405 m_out.appendTo(largeCase, failCase); 2406 ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr( 2407 globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))); 2408 m_out.jump(slowCase); 2409 2410 m_out.appendTo(failCase, slowCase); 2411 ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure)); 2412 m_out.jump(slowCase); 2413 2414 m_out.appendTo(slowCase, continuation); 2415 LValue structureValue = m_out.phi( 2416 m_out.intPtr, largeStructure, failStructure); 2417 ValueFromBlock slowResult = m_out.anchor(vmCall( 2418 m_out.operation(operationNewArrayWithSize), 2419 m_callFrame, structureValue, publicLength)); 2420 m_out.jump(continuation); 2421 2422 m_out.appendTo(continuation, lastNext); 2423 setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); 2424 return; 2425 } 2426 2427 LValue structureValue = m_out.select( 2428 m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)), 2429 m_out.constIntPtr( 2430 globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), 2431 m_out.constIntPtr(structure)); 2432 setJSValue(vmCall(m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength)); 2433 } 2434 2063 2435 void compileAllocatePropertyStorage() 2064 2436 { … … 2103 2475 } 2104 2476 2477 void compileToString() 2478 { 2479 switch (m_node->child1().useKind()) { 2480 case StringObjectUse: { 2481 LValue cell = lowCell(m_node->child1()); 2482 speculateStringObjectForCell(m_node->child1(), cell); 2483 m_interpreter.filter(m_node->child1(), SpecStringObject); 2484 2485 setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue)); 2486 return; 2487 } 2488 2489 case StringOrStringObjectUse: { 2490 LValue cell = lowCell(m_node->child1()); 2491 LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure); 2492 2493 LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject not string case")); 2494 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject continuation")); 2495 2496 ValueFromBlock simpleResult = m_out.anchor(cell); 2497 m_out.branch( 2498 m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())), 2499 continuation, notString); 2500 2501 LBasicBlock lastNext = m_out.appendTo(notString, continuation); 2502 speculateStringObjectForStructure(m_node->child1(), structure); 2503 ValueFromBlock unboxedResult = m_out.anchor( 2504 m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue)); 2505 m_out.jump(continuation); 2506 2507 m_out.appendTo(continuation, lastNext); 2508 setJSValue(m_out.phi(m_out.int64, simpleResult, unboxedResult)); 2509 2510 m_interpreter.filter(m_node->child1(), SpecString | SpecStringObject); 2511 return; 2512 } 2513 2514 case CellUse: 2515 case UntypedUse: { 2516 LValue value; 2517 if (m_node->child1().useKind() == CellUse) 2518 value = lowCell(m_node->child1()); 2519 else 2520 value = lowJSValue(m_node->child1()); 2521 2522 LBasicBlock isCell = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse is cell")); 2523 LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse not string")); 2524 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse continuation")); 2525 2526 LValue isCellPredicate; 2527 if (m_node->child1().useKind() == CellUse) 2528 isCellPredicate = m_out.booleanTrue; 2529 else 2530 isCellPredicate = this->isCell(value); 2531 m_out.branch(isCellPredicate, isCell, notString); 2532 2533 LBasicBlock lastNext = m_out.appendTo(isCell, notString); 2534 ValueFromBlock simpleResult = m_out.anchor(value); 2535 LValue isStringPredicate; 2536 if (m_node->child1()->prediction() & SpecString) { 2537 isStringPredicate = m_out.equal( 2538 m_out.loadPtr(value, m_heaps.JSCell_structure), 2539 m_out.constIntPtr(vm().stringStructure.get())); 2540 } else 2541 isStringPredicate = m_out.booleanFalse; 2542 m_out.branch(isStringPredicate, continuation, notString); 2543 2544 m_out.appendTo(notString, continuation); 2545 LValue operation; 2546 if (m_node->child1().useKind() == CellUse) 2547 operation = m_out.operation(operationToStringOnCell); 2548 else 2549 operation = m_out.operation(operationToString); 2550 ValueFromBlock convertedResult = m_out.anchor(vmCall(operation, m_callFrame, value)); 2551 m_out.jump(continuation); 2552 2553 m_out.appendTo(continuation, lastNext); 2554 setJSValue(m_out.phi(m_out.int64, simpleResult, convertedResult)); 2555 return; 2556 } 2557 2558 default: 2559 RELEASE_ASSERT_NOT_REACHED(); 2560 break; 2561 } 2562 } 2563 2564 void compileMakeRope() 2565 { 2566 LValue kids[3]; 2567 unsigned numKids; 2568 kids[0] = lowCell(m_node->child1()); 2569 kids[1] = lowCell(m_node->child2()); 2570 if (m_node->child3()) { 2571 kids[2] = lowCell(m_node->child3()); 2572 numKids = 3; 2573 } else { 2574 kids[2] = 0; 2575 numKids = 2; 2576 } 2577 2578 LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MakeRope slow path")); 2579 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MakeRope continuation")); 2580 2581 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); 2582 2583 MarkedAllocator& allocator = 2584 vm().heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(JSRopeString)); 2585 2586 LValue result = allocateCell( 2587 m_out.constIntPtr(&allocator), 2588 m_out.constIntPtr(vm().stringStructure.get()), 2589 slowPath); 2590 2591 m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value); 2592 for (unsigned i = 0; i < numKids; ++i) 2593 m_out.storePtr(kids[i], result, m_heaps.JSRopeString_fibers[i]); 2594 for (unsigned i = numKids; i < JSRopeString::s_maxInternalRopeLength; ++i) 2595 m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSRopeString_fibers[i]); 2596 LValue flags = m_out.load32(kids[0], m_heaps.JSString_flags); 2597 LValue length = m_out.load32(kids[0], m_heaps.JSString_length); 2598 for (unsigned i = 1; i < numKids; ++i) { 2599 flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags)); 2600 length = m_out.add(length, m_out.load32(kids[i], m_heaps.JSString_length)); 2601 } 2602 m_out.store32( 2603 m_out.bitAnd(m_out.constInt32(JSString::Is8Bit), flags), 2604 result, m_heaps.JSString_flags); 2605 m_out.store32(length, result, m_heaps.JSString_length); 2606 2607 ValueFromBlock fastResult = m_out.anchor(result); 2608 m_out.jump(continuation); 2609 2610 m_out.appendTo(slowPath, continuation); 2611 ValueFromBlock slowResult; 2612 switch (numKids) { 2613 case 2: 2614 slowResult = m_out.anchor(vmCall( 2615 m_out.operation(operationMakeRope2), m_callFrame, kids[0], kids[1])); 2616 break; 2617 case 3: 2618 slowResult = m_out.anchor(vmCall( 2619 m_out.operation(operationMakeRope3), m_callFrame, kids[0], kids[1], kids[2])); 2620 break; 2621 default: 2622 RELEASE_ASSERT_NOT_REACHED(); 2623 break; 2624 } 2625 m_out.jump(continuation); 2626 2627 m_out.appendTo(continuation, lastNext); 2628 setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); 2629 } 2630 2105 2631 void compileStringCharAt() 2106 2632 { … … 2115 2641 m_out.branch( 2116 2642 m_out.aboveOrEqual( 2117 index, m_out.load32 (base, m_heaps.JSString_length)),2643 index, m_out.load32NonNegative(base, m_heaps.JSString_length)), 2118 2644 slowPath, fastPath); 2119 2645 … … 2211 2737 speculate( 2212 2738 Uncountable, noValue(), 0, 2213 m_out.aboveOrEqual(index, m_out.load32(base, m_heaps.JSString_length))); 2739 m_out.aboveOrEqual( 2740 index, m_out.load32NonNegative(base, m_heaps.JSString_length))); 2214 2741 2215 2742 LValue stringImpl = m_out.loadPtr(base, m_heaps.JSString_value); … … 2346 2873 } 2347 2874 2875 void compileGetCallee() 2876 { 2877 setJSValue(m_out.loadPtr(addressFor(JSStack::Callee))); 2878 } 2879 2880 void compileGetScope() 2881 { 2882 setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope)); 2883 } 2884 2348 2885 void compileGetMyScope() 2349 2886 { … … 2489 3026 void compileCallOrConstruct() 2490 3027 { 2491 // FIXME: This is unacceptably slow.2492 // https://bugs.webkit.org/show_bug.cgi?id=1136212493 2494 J_JITOperation_E function =2495 m_node->op() == Call ? operationFTLCall : operationFTLConstruct;2496 2497 3028 int dummyThisArgument = m_node->op() == Call ? 0 : 1; 2498 2499 3029 int numPassedArgs = m_node->numChildren() - 1; 2500 2501 LValue calleeFrame = m_out.add( 2502 m_callFrame, 2503 m_out.constIntPtr(sizeof(Register) * virtualRegisterForLocal(m_graph.frameRegisterCount()).offset())); 2504 2505 m_out.store32( 2506 m_out.constInt32(numPassedArgs + dummyThisArgument), 2507 payloadFor(calleeFrame, JSStack::ArgumentCount)); 2508 m_out.store64(m_callFrame, calleeFrame, m_heaps.CallFrame_callerFrame); 2509 m_out.store64( 2510 lowJSValue(m_graph.varArgChild(m_node, 0)), 2511 addressFor(calleeFrame, JSStack::Callee)); 2512 2513 for (int i = 0; i < numPassedArgs; ++i) { 2514 m_out.store64( 2515 lowJSValue(m_graph.varArgChild(m_node, 1 + i)), 2516 addressFor(calleeFrame, virtualRegisterForArgument(i + dummyThisArgument).offset())); 2517 } 2518 2519 setJSValue(vmCall(m_out.operation(function), calleeFrame)); 3030 int numArgs = numPassedArgs + dummyThisArgument; 3031 3032 LValue callee = lowJSValue(m_graph.varArgChild(m_node, 0)); 3033 3034 unsigned stackmapID = m_stackmapIDs++; 3035 3036 Vector<LValue> arguments; 3037 arguments.append(m_out.constInt64(stackmapID)); 3038 arguments.append(m_out.constInt32(sizeOfCall())); 3039 arguments.append(constNull(m_out.ref8)); 3040 arguments.append(m_out.constInt32(1 + JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + numArgs)); 3041 arguments.append(callee); // callee -> %rax 3042 arguments.append(getUndef(m_out.int64)); // code block 3043 arguments.append(getUndef(m_out.int64)); // scope chain 3044 arguments.append(callee); // callee -> stack 3045 arguments.append(m_out.constInt64(numArgs)); // argument count and zeros for the tag 3046 if (dummyThisArgument) 3047 arguments.append(getUndef(m_out.int64)); 3048 for (int i = 0; i < numPassedArgs; ++i) 3049 arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i))); 3050 3051 callPreflight(); 3052 3053 LValue call = m_out.call(m_out.patchpointInt64Intrinsic(), arguments); 3054 setInstructionCallingConvention(call, LLVMWebKitJSCallConv); 3055 3056 m_ftlState.jsCalls.append(JSCall(stackmapID, m_node)); 3057 3058 setJSValue(call); 2520 3059 } 2521 3060 … … 2628 3167 m_out.branch( 2629 3168 m_out.notEqual( 2630 m_out.load32 (stringValue, m_heaps.JSString_length),3169 m_out.load32NonNegative(stringValue, m_heaps.JSString_length), 2631 3170 m_out.int32One), 2632 3171 lowBlock(data->fallThrough), lengthIs1); … … 2707 3246 2708 3247 info.m_isInvalidationPoint = true; 3248 } 3249 3250 void compileCheckArgumentsNotCreated() 3251 { 3252 ASSERT(!isEmptySpeculation( 3253 m_state.variables().operand( 3254 m_graph.argumentsRegisterFor(m_node->codeOrigin)).m_type)); 3255 3256 VirtualRegister reg = m_graph.machineArgumentsRegisterFor(m_node->codeOrigin); 3257 speculate(ArgumentsEscaped, noValue(), 0, m_out.notZero64(m_out.load64(addressFor(reg)))); 3258 } 3259 3260 void compileCountExecution() 3261 { 3262 TypedPointer counter = m_out.absolute(m_node->executionCounter()->address()); 3263 m_out.store64(m_out.add(m_out.load64(counter), m_out.constInt64(1)), counter); 2709 3264 } 2710 3265 … … 2925 3480 if (JSArrayBufferView* view = m_graph.tryGetFoldableView(baseEdge.node(), arrayMode)) 2926 3481 return m_out.constInt32(view->length()); 2927 return m_out.load32 (base, m_heaps.JSArrayBufferView_length);3482 return m_out.load32NonNegative(base, m_heaps.JSArrayBufferView_length); 2928 3483 } 2929 3484 … … 2949 3504 case StringUse: { 2950 3505 LValue stringValue = lowString(m_node->child1()); 2951 LValue length = m_out.load32 (stringValue, m_heaps.JSString_length);3506 LValue length = m_out.load32NonNegative(stringValue, m_heaps.JSString_length); 2952 3507 return m_out.notEqual(length, m_out.int32Zero); 2953 3508 } … … 3083 3638 { 3084 3639 LValue isNotInBounds = m_out.aboveOrEqual( 3085 index, m_out.load32 (storage, m_heaps.Butterfly_publicLength));3640 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)); 3086 3641 if (!m_node->arrayMode().isInBounds()) { 3087 3642 LBasicBlock notInBoundsCase = … … 3095 3650 3096 3651 LValue isOutOfBounds = m_out.aboveOrEqual( 3097 index, m_out.load32 (storage, m_heaps.Butterfly_vectorLength));3652 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_vectorLength)); 3098 3653 3099 3654 if (!m_node->arrayMode().isOutOfBounds()) … … 3719 4274 case KnownInt32Use: 3720 4275 case KnownNumberUse: 4276 case KnownStringUse: 3721 4277 ASSERT(!m_interpreter.needsTypeCheck(edge)); 3722 4278 break; … … 3742 4298 speculateString(edge); 3743 4299 break; 4300 case StringObjectUse: 4301 speculateStringObject(edge); 4302 break; 4303 case StringOrStringObjectUse: 4304 speculateStringOrStringObject(edge); 4305 break; 3744 4306 case RealNumberUse: 3745 4307 speculateRealNumber(edge); … … 3753 4315 case BooleanUse: 3754 4316 speculateBoolean(edge); 4317 break; 4318 case NotCellUse: 4319 speculateNotCell(edge); 3755 4320 break; 3756 4321 default: … … 3929 4494 } 3930 4495 4496 void speculateStringObject(Edge edge) 4497 { 4498 if (!m_interpreter.needsTypeCheck(edge, SpecStringObject)) 4499 return; 4500 4501 speculateStringObjectForCell(edge, lowCell(edge)); 4502 m_interpreter.filter(edge, SpecStringObject); 4503 } 4504 4505 void speculateStringOrStringObject(Edge edge) 4506 { 4507 if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject)) 4508 return; 4509 4510 LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("Speculate StringOrStringObject not string case")); 4511 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate StringOrStringObject continuation")); 4512 4513 LValue structure = m_out.loadPtr(lowCell(edge), m_heaps.JSCell_structure); 4514 m_out.branch( 4515 m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())), 4516 continuation, notString); 4517 4518 LBasicBlock lastNext = m_out.appendTo(notString, continuation); 4519 speculateStringObjectForStructure(edge, structure); 4520 m_out.jump(continuation); 4521 4522 m_out.appendTo(continuation, lastNext); 4523 4524 m_interpreter.filter(edge, SpecString | SpecStringObject); 4525 } 4526 4527 void speculateStringObjectForCell(Edge edge, LValue cell) 4528 { 4529 speculateStringObjectForStructure(edge, m_out.loadPtr(cell, m_heaps.JSCell_structure)); 4530 } 4531 4532 void speculateStringObjectForStructure(Edge edge, LValue structure) 4533 { 4534 Structure* stringObjectStructure = 4535 m_graph.globalObjectFor(m_node->codeOrigin)->stringObjectStructure(); 4536 4537 if (m_state.forNode(edge).m_currentKnownStructure.isSubsetOf(StructureSet(stringObjectStructure))) 4538 return; 4539 4540 speculate( 4541 NotStringObject, noValue(), 0, 4542 m_out.notEqual(structure, weakPointer(stringObjectStructure))); 4543 } 4544 3931 4545 void speculateNonNullObject(Edge edge, LValue cell) 3932 4546 { … … 3978 4592 { 3979 4593 lowBoolean(edge); 4594 } 4595 4596 void speculateNotCell(Edge edge) 4597 { 4598 if (!m_interpreter.needsTypeCheck(edge)) 4599 return; 4600 4601 LValue value = lowJSValue(edge); 4602 typeCheck(jsValueValue(value), edge, ~SpecCell, isCell(value)); 3980 4603 } 3981 4604 … … 4107 4730 return; 4108 4731 4109 LBasicBlock didHaveException = FTL_NEW_BLOCK(m_out, ("Did have exception"));4110 4732 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Exception check continuation")); 4111 4733 4112 4734 m_out.branch( 4113 4735 m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))), 4114 didHaveException, continuation); 4115 4116 LBasicBlock lastNext = m_out.appendTo(didHaveException, continuation); 4117 // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622 4118 m_out.crash(); 4119 4120 m_out.appendTo(continuation, lastNext); 4736 m_handleExceptions, continuation); 4737 4738 m_out.appendTo(continuation); 4121 4739 } 4122 4740 … … 4134 4752 ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) 4135 4753 { 4136 if (verboseCompilationEnabled()) 4754 if (verboseCompilationEnabled()) { 4137 4755 dataLog(" OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", m_availability, "\n"); 4756 if (!m_availableRecoveries.isEmpty()) 4757 dataLog(" Available recoveries: ", listDump(m_availableRecoveries), "\n"); 4758 } 4138 4759 4139 4760 ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size()); … … 4179 4800 CodeOrigin codeOrigin) 4180 4801 { 4181 arguments.append(m_callFrame);4182 4802 if (!!lowValue) 4183 4803 arguments.append(lowValue.value()); … … 4247 4867 exit.m_stackmapID = m_stackmapIDs++; 4248 4868 arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize())); 4249 arguments.insert(0, m_out.constInt 32(exit.m_stackmapID));4869 arguments.insert(0, m_out.constInt64(exit.m_stackmapID)); 4250 4870 4251 4871 m_out.call(m_out.stackmapIntrinsic(), arguments); … … 4260 4880 if (tryToSetConstantExitArgument(exit, index, node)) 4261 4881 return; 4882 4883 for (unsigned i = 0; i < m_availableRecoveries.size(); ++i) { 4884 AvailableRecovery recovery = m_availableRecoveries[i]; 4885 if (recovery.node() != node) 4886 continue; 4887 4888 exit.m_values[index] = ExitValue::recovery( 4889 recovery.opcode(), arguments.size(), arguments.size() + 1, 4890 recovery.format()); 4891 arguments.append(recovery.left()); 4892 arguments.append(recovery.right()); 4893 return; 4894 } 4262 4895 4263 4896 LoweredNodeValue value = m_int32Values.get(node); … … 4330 4963 } 4331 4964 4965 bool doesKill(Edge edge) 4966 { 4967 if (edge.doesNotKill()) 4968 return false; 4969 4970 if (edge->hasConstant()) 4971 return false; 4972 4973 return true; 4974 } 4975 4976 void addAvailableRecovery( 4977 Node* node, RecoveryOpcode opcode, LValue left, LValue right, ValueFormat format) 4978 { 4979 m_availableRecoveries.append(AvailableRecovery(node, opcode, left, right, format)); 4980 } 4981 4982 void addAvailableRecovery( 4983 Edge edge, RecoveryOpcode opcode, LValue left, LValue right, ValueFormat format) 4984 { 4985 addAvailableRecovery(edge.node(), opcode, left, right, format); 4986 } 4987 4332 4988 void setInt32(Node* node, LValue value) 4333 4989 { … … 4432 5088 TypedPointer payloadFor(LValue base, int operand) 4433 5089 { 4434 return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));5090 return addressFor(base, operand, PayloadOffset); 4435 5091 } 4436 5092 TypedPointer tagFor(LValue base, int operand) 4437 5093 { 4438 return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); 4439 } 4440 TypedPointer addressFor(int operand) 4441 { 4442 return addressFor(m_callFrame, operand); 4443 } 4444 TypedPointer addressFor(VirtualRegister operand) 4445 { 4446 return addressFor(m_callFrame, operand.offset()); 5094 return addressFor(base, operand, TagOffset); 5095 } 5096 TypedPointer addressFor(int operand, ptrdiff_t offset = 0) 5097 { 5098 return addressFor(VirtualRegister(operand), offset); 5099 } 5100 TypedPointer addressFor(VirtualRegister operand, ptrdiff_t offset = 0) 5101 { 5102 if (operand.isLocal()) 5103 return addressFor(m_captured, operand.offset(), offset); 5104 return addressFor(m_callFrame, operand.offset(), offset); 4447 5105 } 4448 5106 TypedPointer payloadFor(int operand) 4449 5107 { 4450 return payloadFor( m_callFrame, operand);5108 return payloadFor(VirtualRegister(operand)); 4451 5109 } 4452 5110 TypedPointer payloadFor(VirtualRegister operand) 4453 5111 { 4454 return payloadFor(m_callFrame, operand.offset());5112 return addressFor(operand, PayloadOffset); 4455 5113 } 4456 5114 TypedPointer tagFor(int operand) 4457 5115 { 4458 return tagFor( m_callFrame, operand);5116 return tagFor(VirtualRegister(operand)); 4459 5117 } 4460 5118 TypedPointer tagFor(VirtualRegister operand) 4461 5119 { 4462 return tagFor(m_callFrame, operand.offset());5120 return addressFor(operand, TagOffset); 4463 5121 } 4464 5122 … … 4472 5130 4473 5131 LBasicBlock m_prologue; 5132 LBasicBlock m_handleExceptions; 4474 5133 HashMap<BasicBlock*, LBasicBlock> m_blocks; 4475 5134 4476 5135 LValue m_callFrame; 5136 LValue m_captured; 4477 5137 LValue m_tagTypeNumber; 4478 5138 LValue m_tagMask; … … 4490 5150 Operands<Availability> m_availability; 4491 5151 5152 Vector<AvailableRecovery, 3> m_availableRecoveries; 5153 4492 5154 InPlaceAbstractState m_state; 4493 5155 AbstractInterpreter<InPlaceAbstractState> m_interpreter;
Note:
See TracChangeset
for help on using the changeset viewer.