Changeset 245063 in webkit
- Timestamp:
- May 8, 2019 12:38:17 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r245051 r245063 1 2019-05-08 Caio Lima <ticaiolima@gmail.com> 2 3 [BigInt] Add ValueMod into DFG 4 https://bugs.webkit.org/show_bug.cgi?id=186174 5 6 Reviewed by Saam Barati. 7 8 * microbenchmarks/mod-untyped.js: Added. 9 * stress/big-int-mod-osr.js: Added. 10 * stress/value-div-ai-rule.js: Added. 11 * stress/value-mod-ai-rule.js: Added. 12 1 13 2019-05-07 Yusuke Suzuki <ysuzuki@apple.com> 2 14 -
trunk/PerformanceTests/ChangeLog
r244973 r245063 1 2019-05-08 Caio Lima <ticaiolima@gmail.com> 2 3 [BigInt] Add ValueMod into DFG 4 https://bugs.webkit.org/show_bug.cgi?id=186174 5 6 Reviewed by Saam Barati. 7 8 * BigIntBench/big-int-simple-mod.js: Added. 9 1 10 2019-05-06 Saam Barati <sbarati@apple.com> 2 11 -
trunk/Source/JavaScriptCore/ChangeLog
r245051 r245063 1 2019-05-08 Caio Lima <ticaiolima@gmail.com> 2 3 [BigInt] Add ValueMod into DFG 4 https://bugs.webkit.org/show_bug.cgi?id=186174 5 6 Reviewed by Saam Barati. 7 8 This patch is introducing a new DFG node called ValueMod, that is 9 responsible to handle BigInt and Untyped specialization of op_mod. 10 With the introduction of BigInt, we think that cases with 11 ValueMod(Untyped, Untyped) can be more common and we introduced 12 support for such kind of node. 13 14 * dfg/DFGAbstractInterpreter.h: 15 * dfg/DFGAbstractInterpreterInlines.h: 16 (JSC::DFG::AbstractInterpreter<AbstractStateType>::handleConstantDivOp): 17 18 We are abstracting the constant rules of division operations. It 19 includes ArithDiv, ValueDiv, ArithMod and ValueMod, since they perform 20 the same analysis. 21 22 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 23 * dfg/DFGBackwardsPropagationPhase.cpp: 24 (JSC::DFG::BackwardsPropagationPhase::propagate): 25 * dfg/DFGByteCodeParser.cpp: 26 (JSC::DFG::ByteCodeParser::makeSafe): 27 (JSC::DFG::ByteCodeParser::parseBlock): 28 29 Here we check if lhs and rhs have number result to emit ArithMod. 30 Otherwise, we need to fallback to ValueMod and let fixup replace this 31 operation when possible. 32 33 * dfg/DFGClobberize.h: 34 (JSC::DFG::clobberize): 35 36 ValueMod(BigIntUse) doesn't clobberize world because it only calls 37 `operationModBigInt`. 38 39 * dfg/DFGDoesGC.cpp: 40 (JSC::DFG::doesGC): 41 42 ValueMod(BigIntUse) can trigger GC since it allocates intermediate 43 JSBigInt to perform calculation. ValueMod(UntypedUse) can trigger GC 44 because it can execute arbritary code from user. 45 46 * dfg/DFGFixupPhase.cpp: 47 (JSC::DFG::FixupPhase::fixupArithDivInt32): 48 49 Function created to simplify readability of ArithDiv/AirthMod fixup 50 operation. 51 52 (JSC::DFG::FixupPhase::fixupArithDiv): 53 (JSC::DFG::FixupPhase::fixupNode): 54 55 Following the same fixup rules of ArithDiv. 56 57 * dfg/DFGNodeType.h: 58 * dfg/DFGOperations.cpp: 59 (JSC::DFG::binaryOp): 60 * dfg/DFGOperations.h: 61 * dfg/DFGPredictionPropagationPhase.cpp: 62 63 ValueMod follows the same prediction propagation rules of ArithMod and 64 the same rules for `doDoubleVoting`. 65 66 * dfg/DFGSafeToExecute.h: 67 (JSC::DFG::safeToExecute): 68 * dfg/DFGSpeculativeJIT.cpp: 69 (JSC::DFG::SpeculativeJIT::compileValueMod): 70 * dfg/DFGSpeculativeJIT.h: 71 * dfg/DFGSpeculativeJIT32_64.cpp: 72 (JSC::DFG::SpeculativeJIT::compile): 73 * dfg/DFGSpeculativeJIT64.cpp: 74 (JSC::DFG::SpeculativeJIT::compile): 75 * dfg/DFGValidate.cpp: 76 * ftl/FTLCapabilities.cpp: 77 (JSC::FTL::canCompile): 78 * ftl/FTLLowerDFGToB3.cpp: 79 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 80 (JSC::FTL::DFG::LowerDFGToB3::compileValueMod): 81 1 82 2019-05-07 Yusuke Suzuki <ysuzuki@apple.com> 2 83 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
r234086 r245063 254 254 void executeDoubleUnaryOpEffects(Node*, double(*equivalentFunction)(double)); 255 255 256 bool handleConstantDivOp(Node*); 257 256 258 CodeBlock* m_codeBlock; 257 259 Graph& m_graph; -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r244324 r245063 235 235 236 236 template<typename AbstractStateType> 237 bool AbstractInterpreter<AbstractStateType>::handleConstantDivOp(Node* node) 238 { 239 JSValue left = forNode(node->child1()).value(); 240 JSValue right = forNode(node->child2()).value(); 241 242 if (left && right) { 243 NodeType op = node->op(); 244 bool isDivOperation = op == ValueDiv || op == ArithDiv; 245 246 // Only possible case of ValueOp below is UntypedUse, 247 // so we need to reflect clobberize rules. 248 bool isClobbering = op == ValueDiv || op == ValueMod; 249 250 if (left.isInt32() && right.isInt32()) { 251 double doubleResult; 252 if (isDivOperation) 253 doubleResult = left.asNumber() / right.asNumber(); 254 else 255 doubleResult = fmod(left.asNumber(), right.asNumber()); 256 257 if (node->hasArithMode()) { 258 if (!shouldCheckOverflow(node->arithMode())) 259 doubleResult = toInt32(doubleResult); 260 else if (!shouldCheckNegativeZero(node->arithMode())) 261 doubleResult += 0; // Sanitizes zero. 262 } 263 264 JSValue valueResult = jsNumber(doubleResult); 265 if (valueResult.isInt32()) { 266 if (isClobbering) 267 didFoldClobberWorld(); 268 setConstant(node, valueResult); 269 return true; 270 } 271 } else if (left.isNumber() && right.isNumber()) { 272 if (isClobbering) 273 didFoldClobberWorld(); 274 275 if (isDivOperation) 276 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber())); 277 else 278 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber()))); 279 280 return true; 281 } 282 } 283 284 return false; 285 } 286 287 template<typename AbstractStateType> 237 288 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node) 238 289 { … … 912 963 } 913 964 965 case ValueMod: 914 966 case ValueDiv: { 967 if (handleConstantDivOp(node)) 968 break; 969 915 970 if (node->binaryUseKind() == BigIntUse) 916 971 setTypeForNode(node, SpecBigInt); … … 922 977 } 923 978 979 case ArithMod: 924 980 case ArithDiv: { 925 JSValue left = forNode(node->child1()).value(); 926 JSValue right = forNode(node->child2()).value(); 981 if (handleConstantDivOp(node)) 982 break; 983 927 984 switch (node->binaryUseKind()) { 928 985 case Int32Use: 929 if (left && right && left.isInt32() && right.isInt32()) {930 double doubleResult = left.asNumber() / right.asNumber();931 if (!shouldCheckOverflow(node->arithMode()))932 doubleResult = toInt32(doubleResult);933 else if (!shouldCheckNegativeZero(node->arithMode()))934 doubleResult += 0; // Sanitizes zero.935 JSValue valueResult = jsNumber(doubleResult);936 if (valueResult.isInt32()) {937 setConstant(node, valueResult);938 break;939 }940 }941 986 setNonCellTypeForNode(node, SpecInt32Only); 942 987 break; 943 988 case DoubleRepUse: 944 if (left && right && left.isNumber() && right.isNumber()) { 945 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber())); 946 break; 947 } 948 setNonCellTypeForNode(node, 949 typeOfDoubleQuotient( 950 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 951 break; 952 default: 953 RELEASE_ASSERT_NOT_REACHED(); 954 break; 955 } 956 break; 957 } 958 959 case ArithMod: { 960 JSValue left = forNode(node->child1()).value(); 961 JSValue right = forNode(node->child2()).value(); 962 switch (node->binaryUseKind()) { 963 case Int32Use: 964 if (left && right && left.isInt32() && right.isInt32()) { 965 double doubleResult = fmod(left.asNumber(), right.asNumber()); 966 if (!shouldCheckOverflow(node->arithMode())) 967 doubleResult = toInt32(doubleResult); 968 else if (!shouldCheckNegativeZero(node->arithMode())) 969 doubleResult += 0; // Sanitizes zero. 970 JSValue valueResult = jsNumber(doubleResult); 971 if (valueResult.isInt32()) { 972 setConstant(node, valueResult); 973 break; 974 } 975 } 976 setNonCellTypeForNode(node, SpecInt32Only); 977 break; 978 case DoubleRepUse: 979 if (left && right && left.isNumber() && right.isNumber()) { 980 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber()))); 981 break; 982 } 983 setNonCellTypeForNode(node, 984 typeOfDoubleBinaryOp( 985 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 989 if (node->op() == ArithDiv) { 990 setNonCellTypeForNode(node, 991 typeOfDoubleQuotient( 992 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 993 } else { 994 setNonCellTypeForNode(node, 995 typeOfDoubleBinaryOp( 996 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 997 } 998 986 999 break; 987 1000 default: -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r242715 r245063 364 364 } 365 365 366 case ValueMod: 366 367 case ArithMod: { 367 368 flags |= NodeBytecodeUsesAsNumber; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r244939 r245063 936 936 node->mergeFlags(NodeMayNegZeroInDFG); 937 937 938 if (!isX86() && node->op() == ArithMod)938 if (!isX86() && (node->op() == ArithMod || node->op() == ValueMod)) 939 939 return node; 940 940 … … 997 997 case ArithSub: 998 998 case ValueAdd: 999 case ValueMod: 999 1000 case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double. 1000 1001 node->mergeFlags(NodeMayOverflowInt32InBaseline); … … 5107 5108 Node* op1 = get(bytecode.m_lhs); 5108 5109 Node* op2 = get(bytecode.m_rhs); 5109 set(bytecode.m_dst, makeSafe(addToGraph(ArithMod, op1, op2))); 5110 if (op1->hasNumberResult() && op2->hasNumberResult()) 5111 set(bytecode.m_dst, makeSafe(addToGraph(ArithMod, op1, op2))); 5112 else 5113 set(bytecode.m_dst, makeSafe(addToGraph(ValueMod, op1, op2))); 5110 5114 NEXT_OPCODE(op_mod); 5111 5115 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r244324 r245063 681 681 case ValueMul: 682 682 case ValueDiv: 683 case ValueMod: 683 684 if (node->isBinaryUseKind(BigIntUse)) { 684 685 def(PureValue(node)); -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r244324 r245063 380 380 case ValueMul: 381 381 case ValueDiv: 382 case ValueMod: 382 383 case ValueBitNot: 383 384 case ValueNegate: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r244324 r245063 76 76 77 77 private: 78 void fixupArithDiv(Node* node, Edge& leftChild, Edge& rightChild) 79 { 80 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) { 81 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) { 82 fixIntOrBooleanEdge(leftChild); 83 fixIntOrBooleanEdge(rightChild); 84 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) 85 node->setArithMode(Arith::Unchecked); 86 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 87 node->setArithMode(Arith::CheckOverflow); 88 else 89 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 90 return; 91 } 92 93 // This will cause conversion nodes to be inserted later. 94 fixDoubleOrBooleanEdge(leftChild); 95 fixDoubleOrBooleanEdge(rightChild); 96 97 // We don't need to do ref'ing on the children because we're stealing them from 98 // the original division. 99 Node* newDivision = m_insertionSet.insertNode(m_indexInBlock, SpecBytecodeDouble, *node); 100 newDivision->setResult(NodeResultDouble); 101 102 node->setOp(DoubleAsInt32); 103 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge()); 104 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 78 79 void fixupArithDivInt32(Node* node, Edge& leftChild, Edge& rightChild) 80 { 81 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) { 82 fixIntOrBooleanEdge(leftChild); 83 fixIntOrBooleanEdge(rightChild); 84 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) 85 node->setArithMode(Arith::Unchecked); 86 else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 105 87 node->setArithMode(Arith::CheckOverflow); 106 88 else 107 89 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 90 return; 91 } 92 93 // This will cause conversion nodes to be inserted later. 94 fixDoubleOrBooleanEdge(leftChild); 95 fixDoubleOrBooleanEdge(rightChild); 96 97 // We don't need to do ref'ing on the children because we're stealing them from 98 // the original division. 99 Node* newDivision = m_insertionSet.insertNode(m_indexInBlock, SpecBytecodeDouble, *node); 100 newDivision->setResult(NodeResultDouble); 101 102 node->setOp(DoubleAsInt32); 103 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge()); 104 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 105 node->setArithMode(Arith::CheckOverflow); 106 else 107 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 108 109 } 110 111 void fixupArithDiv(Node* node, Edge& leftChild, Edge& rightChild) 112 { 113 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) { 114 fixupArithDivInt32(node, leftChild, rightChild); 108 115 return; 109 116 } … … 475 482 fixEdge<BigIntUse>(node->child1()); 476 483 fixEdge<BigIntUse>(node->child2()); 484 node->clearFlags(NodeMustGenerate); 477 485 break; 478 486 } … … 509 517 } 510 518 519 case ValueMod: 511 520 case ValueDiv: { 512 521 Edge& leftChild = node->child1(); … … 516 525 fixEdge<BigIntUse>(leftChild); 517 526 fixEdge<BigIntUse>(rightChild); 527 node->clearFlags(NodeMustGenerate); 518 528 break; 519 529 } … … 524 534 break; 525 535 } 526 node->setOp(ArithDiv); 536 537 if (op == ValueDiv) 538 node->setOp(ArithDiv); 539 else 540 node->setOp(ArithMod); 541 527 542 node->setResult(NodeResultNumber); 528 543 fixupArithDiv(node, leftChild, rightChild); -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r244324 r245063 180 180 macro(ValueMul, NodeResultJS | NodeMustGenerate) \ 181 181 macro(ValueDiv, NodeResultJS | NodeMustGenerate) \ 182 macro(ValueMod, NodeResultJS | NodeMustGenerate) \ 182 183 \ 183 184 /* Add of values that always convers its inputs to strings. May have two or three kids. */\ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r245017 r245063 214 214 } 215 215 216 template<typename BigIntOperation, typename NumberOperation> 217 static ALWAYS_INLINE EncodedJSValue binaryOp(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, NumberOperation&& numberOp, const char* errorMessage) 218 { 219 VM* vm = &exec->vm(); 220 NativeCallFrameTracer tracer(vm, exec); 221 auto scope = DECLARE_THROW_SCOPE(*vm); 222 223 JSValue op1 = JSValue::decode(encodedOp1); 224 JSValue op2 = JSValue::decode(encodedOp2); 225 226 auto leftNumeric = op1.toNumeric(exec); 227 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 228 auto rightNumeric = op2.toNumeric(exec); 229 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 230 231 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 232 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) 233 RELEASE_AND_RETURN(scope, JSValue::encode(bigIntOp(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)))); 234 235 return throwVMTypeError(exec, scope, errorMessage); 236 } 237 238 scope.release(); 239 240 return JSValue::encode(jsNumber(numberOp(WTF::get<double>(leftNumeric), WTF::get<double>(rightNumeric)))); 241 } 242 216 243 template<typename BigIntOperation, typename Int32Operation> 217 244 static ALWAYS_INLINE EncodedJSValue bitwiseBinaryOp(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, Int32Operation&& int32Op, const char* errorMessage) … … 381 408 } 382 409 410 EncodedJSValue JIT_OPERATION operationValueMod(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 411 { 412 auto bigIntOp = [] (ExecState* exec, JSBigInt* left, JSBigInt* right) -> JSBigInt* { 413 return JSBigInt::remainder(exec, left, right); 414 }; 415 416 auto numberOp = [] (double left, double right) -> double { 417 return jsMod(left, right); 418 }; 419 420 return binaryOp(exec, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in remainder operation."); 421 } 422 383 423 EncodedJSValue JIT_OPERATION operationValueBitNot(ExecState* exec, EncodedJSValue encodedOp1) 384 424 { … … 498 538 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 499 539 { 500 VM* vm = &exec->vm(); 501 NativeCallFrameTracer tracer(vm, exec); 502 auto scope = DECLARE_THROW_SCOPE(*vm); 503 504 JSValue op1 = JSValue::decode(encodedOp1); 505 JSValue op2 = JSValue::decode(encodedOp2); 506 507 auto leftNumeric = op1.toNumeric(exec); 508 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 509 auto rightNumeric = op2.toNumeric(exec); 510 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 511 512 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 513 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 514 JSBigInt* result = JSBigInt::divide(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 515 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 516 return JSValue::encode(result); 517 } 518 519 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in division operation."); 520 } 521 522 scope.release(); 523 524 double a = WTF::get<double>(leftNumeric); 525 double b = WTF::get<double>(rightNumeric); 526 return JSValue::encode(jsNumber(a / b)); 540 auto bigIntOp = [] (ExecState* exec, JSBigInt* left, JSBigInt* right) -> JSBigInt* { 541 return JSBigInt::divide(exec, left, right); 542 }; 543 544 auto numberOp = [] (double left, double right) -> double { 545 return left / right; 546 }; 547 548 return binaryOp(exec, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in division operation."); 527 549 } 528 550 … … 1353 1375 } 1354 1376 1377 JSCell* JIT_OPERATION operationModBigInt(ExecState* exec, JSCell* op1, JSCell* op2) 1378 { 1379 VM* vm = &exec->vm(); 1380 NativeCallFrameTracer tracer(vm, exec); 1381 1382 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1); 1383 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); 1384 1385 return JSBigInt::remainder(exec, leftOperand, rightOperand); 1386 } 1387 1355 1388 JSCell* JIT_OPERATION operationDivBigInt(ExecState* exec, JSCell* op1, JSCell* op2) 1356 1389 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r244067 r245063 51 51 EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL; 52 52 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL; 53 EncodedJSValue JIT_OPERATION operationValueMod(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 53 54 EncodedJSValue JIT_OPERATION operationValueBitNot(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL; 54 55 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; … … 169 170 JSCell* JIT_OPERATION operationSubBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 170 171 JSCell* JIT_OPERATION operationMulBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 172 JSCell* JIT_OPERATION operationModBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 171 173 JSCell* JIT_OPERATION operationDivBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 172 174 JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r244324 r245063 349 349 350 350 case ValueDiv: 351 case ValueMod: 351 352 case ArithDiv: 352 353 case ArithMod: { … … 361 362 else 362 363 changed |= mergePrediction(SpecBytecodeDouble); 363 } else if ( op == ValueDiv&& isBigIntSpeculation(left) && isBigIntSpeculation(right))364 } else if ((op == ValueDiv || op == ValueMod) && isBigIntSpeculation(left) && isBigIntSpeculation(right)) 364 365 changed |= mergePrediction(SpecBigInt); 365 366 else { 366 367 changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); 367 if ( op == ValueDiv&& (node->mayHaveBigIntResult()368 if ((op == ValueDiv || op == ValueMod) && (node->mayHaveBigIntResult() 368 369 || (left & SpecBigInt) 369 370 || (right & SpecBigInt))) … … 602 603 case ArithMod: 603 604 case ValueDiv: 605 case ValueMod: 604 606 case ArithDiv: { 605 607 SpeculatedType left = node->child1()->prediction(); … … 1118 1120 case ValueMul: 1119 1121 case ValueDiv: 1122 case ValueMod: 1120 1123 case ArithAdd: 1121 1124 case ArithSub: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r244324 r245063 239 239 case ValueMul: 240 240 case ValueDiv: 241 case ValueMod: 241 242 case TryGetById: 242 243 case DeleteById: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r244760 r245063 5220 5220 m_jit.exceptionCheck(); 5221 5221 doubleResult(result.fpr(), node); 5222 } 5223 5224 void SpeculativeJIT::compileValueMod(Node* node) 5225 { 5226 Edge& leftChild = node->child1(); 5227 Edge& rightChild = node->child2(); 5228 5229 if (node->binaryUseKind() == BigIntUse) { 5230 SpeculateCellOperand left(this, leftChild); 5231 SpeculateCellOperand right(this, rightChild); 5232 GPRReg leftGPR = left.gpr(); 5233 GPRReg rightGPR = right.gpr(); 5234 5235 speculateBigInt(leftChild, leftGPR); 5236 speculateBigInt(rightChild, rightGPR); 5237 5238 flushRegisters(); 5239 GPRFlushedCallResult result(this); 5240 GPRReg resultGPR = result.gpr(); 5241 5242 callOperation(operationModBigInt, resultGPR, leftGPR, rightGPR); 5243 5244 m_jit.exceptionCheck(); 5245 cellResult(resultGPR, node); 5246 return; 5247 } 5248 5249 DFG_ASSERT(m_jit.graph(), node, node->binaryUseKind() == UntypedUse, node->binaryUseKind()); 5250 JSValueOperand op1(this, leftChild); 5251 JSValueOperand op2(this, rightChild); 5252 JSValueRegs op1Regs = op1.jsValueRegs(); 5253 JSValueRegs op2Regs = op2.jsValueRegs(); 5254 flushRegisters(); 5255 JSValueRegsFlushedCallResult result(this); 5256 JSValueRegs resultRegs = result.regs(); 5257 callOperation(operationValueMod, resultRegs, op1Regs, op2Regs); 5258 m_jit.exceptionCheck(); 5259 jsValueResult(resultRegs, node); 5222 5260 } 5223 5261 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r242812 r245063 1357 1357 void compileArithDiv(Node*); 1358 1358 void compileArithFRound(Node*); 1359 void compileValueMod(Node*); 1359 1360 void compileArithMod(Node*); 1360 1361 void compileArithPow(Node*); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r244324 r245063 2085 2085 case ArithDiv: { 2086 2086 compileArithDiv(node); 2087 break; 2088 } 2089 2090 case ValueMod: { 2091 compileValueMod(node); 2087 2092 break; 2088 2093 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r244324 r245063 2231 2231 case ArithDiv: { 2232 2232 compileArithDiv(node); 2233 break; 2234 } 2235 2236 case ValueMod: { 2237 compileValueMod(node); 2233 2238 break; 2234 2239 } -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r244324 r245063 258 258 case ValueMul: 259 259 case ValueDiv: 260 case ValueMod: 260 261 case ArithAdd: 261 262 case ArithSub: -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r244811 r245063 99 99 case ValueMul: 100 100 case ValueDiv: 101 case ValueMod: 101 102 case StrCat: 102 103 case ArithAdd: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r245051 r245063 781 781 compileArithDiv(); 782 782 break; 783 case ValueMod: 784 compileValueMod(); 785 break; 783 786 case ArithMod: 784 787 compileArithMod(); … … 2547 2550 } 2548 2551 2552 void compileValueMod() 2553 { 2554 if (m_node->binaryUseKind() == BigIntUse) { 2555 LValue left = lowBigInt(m_node->child1()); 2556 LValue right = lowBigInt(m_node->child2()); 2557 2558 LValue result = vmCall(pointerType(), m_out.operation(operationModBigInt), m_callFrame, left, right); 2559 setJSValue(result); 2560 return; 2561 } 2562 2563 DFG_ASSERT(m_graph, m_node, m_node->binaryUseKind() == UntypedUse, m_node->binaryUseKind()); 2564 LValue left = lowJSValue(m_node->child1()); 2565 LValue right = lowJSValue(m_node->child2()); 2566 LValue result = vmCall(Int64, m_out.operation(operationValueMod), m_callFrame, left, right); 2567 setJSValue(result); 2568 } 2569 2549 2570 void compileArithMod() 2550 2571 {
Note: See TracChangeset
for help on using the changeset viewer.