Changeset 206134 in webkit
- Timestamp:
- Sep 19, 2016 5:48:39 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r206082 r206134 1 2016-09-19 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Make the rounding-related nodes support any type 4 https://bugs.webkit.org/show_bug.cgi?id=161895 5 6 Reviewed by Geoffrey Garen. 7 8 * stress/arith-ceil-on-various-types.js: Added. 9 * stress/arith-floor-on-various-types.js: Added. 10 * stress/arith-round-on-various-types.js: Added. 11 * stress/arith-trunc-on-various-types.js: Added. 12 1 13 2016-09-18 Yusuke Suzuki <utatane.tea@gmail.com> 2 14 -
trunk/Source/JavaScriptCore/ChangeLog
r206128 r206134 1 2016-09-19 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Make the rounding-related nodes support any type 4 https://bugs.webkit.org/show_bug.cgi?id=161895 5 6 Reviewed by Geoffrey Garen. 7 8 This patch changes ArithRound, ArithFloor, ArithCeil and ArithTrunc 9 to support polymorphic input without exiting on entry. 10 11 * dfg/DFGAbstractInterpreterInlines.h: 12 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 13 * dfg/DFGByteCodeParser.cpp: 14 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 15 The 4 functions ignore any input past the first argument. It is okay 16 to use the nodes with the first argument and let the Phantoms keep 17 the remaining arguments live. 18 19 * dfg/DFGClobberize.h: 20 (JSC::DFG::clobberize): 21 * dfg/DFGFixupPhase.cpp: 22 (JSC::DFG::FixupPhase::fixupNode): 23 Our fixup had the issue we have seen on previous nodes: unaryArithShouldSpeculateInt32() 24 prevents us from picking a good type if we do not see any double. 25 26 * dfg/DFGNodeType.h: 27 * dfg/DFGOperations.cpp: 28 * dfg/DFGOperations.h: 29 * dfg/DFGPredictionPropagationPhase.cpp: 30 Prediction propagation of those nodes are fully determined 31 from their flags and results's prediction. They are moved 32 to the invariant processing. 33 34 * dfg/DFGSpeculativeJIT.cpp: 35 (JSC::DFG::SpeculativeJIT::compileArithRounding): 36 * ftl/FTLLowerDFGToB3.cpp: 37 (JSC::FTL::DFG::LowerDFGToB3::compileArithRound): 38 (JSC::FTL::DFG::LowerDFGToB3::compileArithFloor): 39 (JSC::FTL::DFG::LowerDFGToB3::compileArithCeil): 40 (JSC::FTL::DFG::LowerDFGToB3::compileArithTrunc): 41 1 42 2016-09-19 Yusuke Suzuki <utatane.tea@gmail.com> 2 43 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r206098 r206134 906 906 case ArithTrunc: { 907 907 JSValue operand = forNode(node->child1()).value(); 908 if ( operand && operand.isNumber()) {908 if (Optional<double> number = operand.toNumberFromPrimitive()) { 909 909 double roundedValue = 0; 910 910 if (node->op() == ArithRound) 911 roundedValue = jsRound( operand.asNumber());911 roundedValue = jsRound(*number); 912 912 else if (node->op() == ArithFloor) 913 roundedValue = floor( operand.asNumber());913 roundedValue = floor(*number); 914 914 else if (node->op() == ArithCeil) 915 roundedValue = ceil( operand.asNumber());915 roundedValue = ceil(*number); 916 916 else { 917 917 ASSERT(node->op() == ArithTrunc); 918 roundedValue = trunc(operand.asNumber()); 919 } 920 918 roundedValue = trunc(*number); 919 } 920 921 if (node->child1().useKind() == UntypedUse) { 922 setConstant(node, jsNumber(roundedValue)); 923 break; 924 } 921 925 if (producesInteger(node->arithRoundingMode())) { 922 926 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue); … … 937 941 } 938 942 } 939 if (producesInteger(node->arithRoundingMode())) 940 forNode(node).setType(SpecInt32Only); 941 else 942 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type)); 943 if (node->child1().useKind() == DoubleRepUse) { 944 if (producesInteger(node->arithRoundingMode())) 945 forNode(node).setType(SpecInt32Only); 946 else if (node->child1().useKind() == DoubleRepUse) 947 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type)); 948 } else { 949 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse); 950 forNode(node).setType(SpecFullNumber); 951 } 943 952 break; 944 953 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r206104 r206134 2442 2442 return true; 2443 2443 } 2444 if (argumentCountIncludingThis == 2) { 2445 insertChecks(); 2446 Node* operand = get(virtualRegisterForArgument(1, registerOffset)); 2447 NodeType op; 2448 if (intrinsic == RoundIntrinsic) 2449 op = ArithRound; 2450 else if (intrinsic == FloorIntrinsic) 2451 op = ArithFloor; 2452 else if (intrinsic == CeilIntrinsic) 2453 op = ArithCeil; 2454 else { 2455 ASSERT(intrinsic == TruncIntrinsic); 2456 op = ArithTrunc; 2457 } 2458 Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand); 2459 set(VirtualRegister(resultOperand), roundNode); 2460 return true; 2461 } 2462 return false; 2444 insertChecks(); 2445 Node* operand = get(virtualRegisterForArgument(1, registerOffset)); 2446 NodeType op; 2447 if (intrinsic == RoundIntrinsic) 2448 op = ArithRound; 2449 else if (intrinsic == FloorIntrinsic) 2450 op = ArithFloor; 2451 else if (intrinsic == CeilIntrinsic) 2452 op = ArithCeil; 2453 else { 2454 ASSERT(intrinsic == TruncIntrinsic); 2455 op = ArithTrunc; 2456 } 2457 Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand); 2458 set(VirtualRegister(resultOperand), roundNode); 2459 return true; 2463 2460 } 2464 2461 case IMulIntrinsic: { -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r206098 r206134 360 360 case ArithCeil: 361 361 case ArithTrunc: 362 def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode()))); 362 if (node->child1().useKind() == DoubleRepUse) 363 def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode()))); 364 else { 365 read(World); 366 write(Heap); 367 } 363 368 return; 364 369 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r206098 r206134 377 377 case ArithCeil: 378 378 case ArithTrunc: { 379 if ( m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {379 if (node->child1()->shouldSpeculateInt32OrBoolean() && m_graph.roundShouldSpeculateInt32(node, FixupPass)) { 380 380 fixIntOrBooleanEdge(node->child1()); 381 381 insertCheck<Int32Use>(m_indexInBlock, node->child1().node()); … … 383 383 break; 384 384 } 385 fixDoubleOrBooleanEdge(node->child1()); 386 387 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) { 388 node->setResult(NodeResultInt32); 389 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 390 node->setArithRoundingMode(Arith::RoundingMode::Int32); 391 else 392 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck); 393 } else { 394 node->setResult(NodeResultDouble); 395 node->setArithRoundingMode(Arith::RoundingMode::Double); 396 } 385 if (node->child1()->shouldSpeculateNotCell()) { 386 fixDoubleOrBooleanEdge(node->child1()); 387 388 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) { 389 node->setResult(NodeResultInt32); 390 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 391 node->setArithRoundingMode(Arith::RoundingMode::Int32); 392 else 393 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck); 394 } else { 395 node->setResult(NodeResultDouble); 396 node->setArithRoundingMode(Arith::RoundingMode::Double); 397 } 398 node->clearFlags(NodeMustGenerate); 399 } else 400 fixEdge<UntypedUse>(node->child1()); 397 401 break; 398 402 } -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r206098 r206134 156 156 macro(ArithPow, NodeResultDouble) \ 157 157 macro(ArithRandom, NodeResultDouble | NodeMustGenerate) \ 158 macro(ArithRound, NodeResultNumber ) \159 macro(ArithFloor, NodeResultNumber ) \160 macro(ArithCeil, NodeResultNumber ) \161 macro(ArithTrunc, NodeResultNumber ) \158 macro(ArithRound, NodeResultNumber | NodeMustGenerate) \ 159 macro(ArithFloor, NodeResultNumber | NodeMustGenerate) \ 160 macro(ArithCeil, NodeResultNumber | NodeMustGenerate) \ 161 macro(ArithTrunc, NodeResultNumber | NodeMustGenerate) \ 162 162 macro(ArithSqrt, NodeResultDouble | NodeMustGenerate) \ 163 163 macro(ArithSin, NodeResultDouble | NodeMustGenerate) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r205974 r206134 443 443 } 444 444 445 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument) 446 { 447 VM* vm = &exec->vm(); 448 NativeCallFrameTracer tracer(vm, exec); 449 auto scope = DECLARE_THROW_SCOPE(*vm); 450 451 JSValue argument = JSValue::decode(encodedArgument); 452 double valueOfArgument = argument.toNumber(exec); 453 if (UNLIKELY(scope.exception())) 454 return JSValue::encode(JSValue()); 455 return JSValue::encode(jsNumber(jsRound(valueOfArgument))); 456 } 457 458 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument) 459 { 460 VM* vm = &exec->vm(); 461 NativeCallFrameTracer tracer(vm, exec); 462 auto scope = DECLARE_THROW_SCOPE(*vm); 463 464 JSValue argument = JSValue::decode(encodedArgument); 465 double valueOfArgument = argument.toNumber(exec); 466 if (UNLIKELY(scope.exception())) 467 return JSValue::encode(JSValue()); 468 return JSValue::encode(jsNumber(floor(valueOfArgument))); 469 } 470 471 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument) 472 { 473 VM* vm = &exec->vm(); 474 NativeCallFrameTracer tracer(vm, exec); 475 auto scope = DECLARE_THROW_SCOPE(*vm); 476 477 JSValue argument = JSValue::decode(encodedArgument); 478 double valueOfArgument = argument.toNumber(exec); 479 if (UNLIKELY(scope.exception())) 480 return JSValue::encode(JSValue()); 481 return JSValue::encode(jsNumber(ceil(valueOfArgument))); 482 } 483 484 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument) 485 { 486 VM* vm = &exec->vm(); 487 NativeCallFrameTracer tracer(vm, exec); 488 auto scope = DECLARE_THROW_SCOPE(*vm); 489 490 JSValue argument = JSValue::decode(encodedArgument); 491 double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec); 492 if (UNLIKELY(scope.exception())) 493 return JSValue::encode(JSValue()); 494 return JSValue::encode(jsNumber(truncatedValueOfArgument)); 495 } 496 445 497 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index) 446 498 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r205974 r206134 1 1 /* 2 * Copyright (C) 2011, 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 62 62 double JIT_OPERATION operationArithSin(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL; 63 63 double JIT_OPERATION operationArithSqrt(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL; 64 EncodedJSValue JIT_OPERATION operationArithRound(ExecState*, EncodedJSValue) WTF_INTERNAL; 65 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState*, EncodedJSValue) WTF_INTERNAL; 66 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState*, EncodedJSValue) WTF_INTERNAL; 67 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState*, EncodedJSValue) WTF_INTERNAL; 64 68 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL; 65 69 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r206098 r206134 316 316 changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); 317 317 } 318 break;319 }320 321 case ArithRound:322 case ArithFloor:323 case ArithCeil:324 case ArithTrunc: {325 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, m_pass))326 changed |= setPrediction(SpecInt32Only);327 else328 changed |= setPrediction(SpecBytecodeDouble);329 318 break; 330 319 } … … 777 766 } 778 767 768 case ArithRound: 769 case ArithFloor: 770 case ArithCeil: 771 case ArithTrunc: { 772 if (isInt32OrBooleanSpeculation(m_currentNode->getHeapPrediction()) 773 && m_graph.roundShouldSpeculateInt32(m_currentNode, m_pass)) 774 setPrediction(SpecInt32Only); 775 else 776 setPrediction(SpecBytecodeDouble); 777 break; 778 } 779 779 780 case ArithRandom: { 780 781 setPrediction(SpecDoubleReal); … … 949 950 case ArithDiv: 950 951 case ArithMod: 951 case ArithRound:952 case ArithFloor:953 case ArithCeil:954 case ArithTrunc:955 952 case ArithAbs: 956 953 case GetByVal: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r206065 r206134 4916 4916 void SpeculativeJIT::compileArithRounding(Node* node) 4917 4917 { 4918 ASSERT(node->child1().useKind() == DoubleRepUse); 4919 4920 SpeculateDoubleOperand value(this, node->child1()); 4921 FPRReg valueFPR = value.fpr(); 4922 4923 auto setResult = [&] (FPRReg resultFPR) { 4924 if (producesInteger(node->arithRoundingMode())) { 4925 GPRTemporary roundedResultAsInt32(this); 4926 FPRTemporary scratch(this); 4927 FPRReg scratchFPR = scratch.fpr(); 4928 GPRReg resultGPR = roundedResultAsInt32.gpr(); 4929 JITCompiler::JumpList failureCases; 4930 m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode())); 4931 speculationCheck(Overflow, JSValueRegs(), node, failureCases); 4932 4933 int32Result(resultGPR, node); 4934 } else 4935 doubleResult(resultFPR, node); 4936 }; 4937 4938 if (m_jit.supportsFloatingPointRounding()) { 4939 switch (node->op()) { 4940 case ArithRound: { 4941 FPRTemporary result(this); 4942 FPRReg resultFPR = result.fpr(); 4943 if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) { 4944 static const double halfConstant = 0.5; 4945 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR); 4946 m_jit.addDouble(valueFPR, resultFPR); 4947 m_jit.floorDouble(resultFPR, resultFPR); 4948 } else { 4949 m_jit.ceilDouble(valueFPR, resultFPR); 4950 FPRTemporary realPart(this); 4951 FPRReg realPartFPR = realPart.fpr(); 4952 m_jit.subDouble(resultFPR, valueFPR, realPartFPR); 4953 4918 if (node->child1().useKind() == DoubleRepUse) { 4919 SpeculateDoubleOperand value(this, node->child1()); 4920 FPRReg valueFPR = value.fpr(); 4921 4922 auto setResult = [&] (FPRReg resultFPR) { 4923 if (producesInteger(node->arithRoundingMode())) { 4924 GPRTemporary roundedResultAsInt32(this); 4954 4925 FPRTemporary scratch(this); 4955 4926 FPRReg scratchFPR = scratch.fpr(); 4956 static const double halfConstant = 0.5; 4957 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR); 4958 4959 JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR); 4960 static const double oneConstant = -1.0; 4961 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR); 4962 m_jit.addDouble(scratchFPR, resultFPR); 4963 shouldUseCeiled.link(&m_jit); 4927 GPRReg resultGPR = roundedResultAsInt32.gpr(); 4928 JITCompiler::JumpList failureCases; 4929 m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode())); 4930 speculationCheck(Overflow, JSValueRegs(), node, failureCases); 4931 4932 int32Result(resultGPR, node); 4933 } else 4934 doubleResult(resultFPR, node); 4935 }; 4936 4937 if (m_jit.supportsFloatingPointRounding()) { 4938 switch (node->op()) { 4939 case ArithRound: { 4940 FPRTemporary result(this); 4941 FPRReg resultFPR = result.fpr(); 4942 if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) { 4943 static const double halfConstant = 0.5; 4944 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR); 4945 m_jit.addDouble(valueFPR, resultFPR); 4946 m_jit.floorDouble(resultFPR, resultFPR); 4947 } else { 4948 m_jit.ceilDouble(valueFPR, resultFPR); 4949 FPRTemporary realPart(this); 4950 FPRReg realPartFPR = realPart.fpr(); 4951 m_jit.subDouble(resultFPR, valueFPR, realPartFPR); 4952 4953 FPRTemporary scratch(this); 4954 FPRReg scratchFPR = scratch.fpr(); 4955 static const double halfConstant = 0.5; 4956 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR); 4957 4958 JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR); 4959 static const double oneConstant = -1.0; 4960 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR); 4961 m_jit.addDouble(scratchFPR, resultFPR); 4962 shouldUseCeiled.link(&m_jit); 4963 } 4964 setResult(resultFPR); 4965 return; 4966 } 4967 4968 case ArithFloor: { 4969 FPRTemporary rounded(this); 4970 FPRReg resultFPR = rounded.fpr(); 4971 m_jit.floorDouble(valueFPR, resultFPR); 4972 setResult(resultFPR); 4973 return; 4974 } 4975 4976 case ArithCeil: { 4977 FPRTemporary rounded(this); 4978 FPRReg resultFPR = rounded.fpr(); 4979 m_jit.ceilDouble(valueFPR, resultFPR); 4980 setResult(resultFPR); 4981 return; 4982 } 4983 4984 case ArithTrunc: { 4985 FPRTemporary rounded(this); 4986 FPRReg resultFPR = rounded.fpr(); 4987 m_jit.roundTowardZeroDouble(valueFPR, resultFPR); 4988 setResult(resultFPR); 4989 return; 4990 } 4991 4992 default: 4993 RELEASE_ASSERT_NOT_REACHED(); 4994 } 4995 } else { 4996 flushRegisters(); 4997 FPRResult roundedResultAsDouble(this); 4998 FPRReg resultFPR = roundedResultAsDouble.fpr(); 4999 if (node->op() == ArithRound) 5000 callOperation(jsRound, resultFPR, valueFPR); 5001 else if (node->op() == ArithFloor) 5002 callOperation(floor, resultFPR, valueFPR); 5003 else if (node->op() == ArithCeil) 5004 callOperation(ceil, resultFPR, valueFPR); 5005 else { 5006 ASSERT(node->op() == ArithTrunc); 5007 callOperation(trunc, resultFPR, valueFPR); 4964 5008 } 4965 5009 setResult(resultFPR); 4966 return; 4967 } 4968 4969 case ArithFloor: { 4970 FPRTemporary rounded(this); 4971 FPRReg resultFPR = rounded.fpr(); 4972 m_jit.floorDouble(valueFPR, resultFPR); 4973 setResult(resultFPR); 4974 return; 4975 } 4976 4977 case ArithCeil: { 4978 FPRTemporary rounded(this); 4979 FPRReg resultFPR = rounded.fpr(); 4980 m_jit.ceilDouble(valueFPR, resultFPR); 4981 setResult(resultFPR); 4982 return; 4983 } 4984 4985 case ArithTrunc: { 4986 FPRTemporary rounded(this); 4987 FPRReg resultFPR = rounded.fpr(); 4988 m_jit.roundTowardZeroDouble(valueFPR, resultFPR); 4989 setResult(resultFPR); 4990 return; 4991 } 4992 4993 default: 4994 RELEASE_ASSERT_NOT_REACHED(); 4995 } 4996 } else { 4997 flushRegisters(); 4998 FPRResult roundedResultAsDouble(this); 4999 FPRReg resultFPR = roundedResultAsDouble.fpr(); 5000 if (node->op() == ArithRound) 5001 callOperation(jsRound, resultFPR, valueFPR); 5002 else if (node->op() == ArithFloor) 5003 callOperation(floor, resultFPR, valueFPR); 5004 else if (node->op() == ArithCeil) 5005 callOperation(ceil, resultFPR, valueFPR); 5006 else { 5007 ASSERT(node->op() == ArithTrunc); 5008 callOperation(trunc, resultFPR, valueFPR); 5009 } 5010 m_jit.exceptionCheck(); 5011 setResult(resultFPR); 5012 } 5010 } 5011 return; 5012 } 5013 5014 DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse); 5015 5016 JSValueOperand argument(this, node->child1()); 5017 JSValueRegs argumentRegs = argument.jsValueRegs(); 5018 #if USE(JSVALUE64) 5019 GPRTemporary result(this); 5020 JSValueRegs resultRegs = JSValueRegs(result.gpr()); 5021 #else 5022 GPRTemporary resultTag(this); 5023 GPRTemporary resultPayload(this); 5024 JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr()); 5025 #endif 5026 flushRegisters(); 5027 J_JITOperation_EJ operation = nullptr; 5028 if (node->op() == ArithRound) 5029 operation = operationArithRound; 5030 else if (node->op() == ArithFloor) 5031 operation = operationArithFloor; 5032 else if (node->op() == ArithCeil) 5033 operation = operationArithCeil; 5034 else { 5035 ASSERT(node->op() == ArithTrunc); 5036 operation = operationArithTrunc; 5037 } 5038 callOperation(operation, resultRegs, argumentRegs); 5039 m_jit.exceptionCheck(); 5040 jsValueResult(resultRegs, node); 5013 5041 } 5014 5042 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r206098 r206134 2261 2261 void compileArithRound() 2262 2262 { 2263 LValue result = nullptr; 2264 2265 if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) { 2263 if (m_node->child1().useKind() == DoubleRepUse) { 2264 LValue result = nullptr; 2265 if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) { 2266 LValue value = lowDouble(m_node->child1()); 2267 result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5))); 2268 } else { 2269 LBasicBlock realPartIsMoreThanHalf = m_out.newBlock(); 2270 LBasicBlock continuation = m_out.newBlock(); 2271 2272 LValue value = lowDouble(m_node->child1()); 2273 LValue integerValue = m_out.doubleCeil(value); 2274 ValueFromBlock integerValueResult = m_out.anchor(integerValue); 2275 2276 LValue realPart = m_out.doubleSub(integerValue, value); 2277 2278 m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation)); 2279 2280 LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation); 2281 LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1)); 2282 ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown); 2283 m_out.jump(continuation); 2284 m_out.appendTo(continuation, lastNext); 2285 2286 result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult); 2287 } 2288 2289 if (producesInteger(m_node->arithRoundingMode())) { 2290 LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())); 2291 setInt32(integerValue); 2292 } else 2293 setDouble(result); 2294 return; 2295 } 2296 2297 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); 2298 LValue argument = lowJSValue(m_node->child1()); 2299 setJSValue(vmCall(Int64, m_out.operation(operationArithRound), m_callFrame, argument)); 2300 } 2301 2302 void compileArithFloor() 2303 { 2304 if (m_node->child1().useKind() == DoubleRepUse) { 2266 2305 LValue value = lowDouble(m_node->child1()); 2267 result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5))); 2268 } else { 2269 LBasicBlock realPartIsMoreThanHalf = m_out.newBlock(); 2270 LBasicBlock continuation = m_out.newBlock(); 2271 2306 LValue integerValue = m_out.doubleFloor(value); 2307 if (producesInteger(m_node->arithRoundingMode())) 2308 setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode()))); 2309 else 2310 setDouble(integerValue); 2311 return; 2312 } 2313 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); 2314 LValue argument = lowJSValue(m_node->child1()); 2315 setJSValue(vmCall(Int64, m_out.operation(operationArithFloor), m_callFrame, argument)); 2316 } 2317 2318 void compileArithCeil() 2319 { 2320 if (m_node->child1().useKind() == DoubleRepUse) { 2272 2321 LValue value = lowDouble(m_node->child1()); 2273 2322 LValue integerValue = m_out.doubleCeil(value); 2274 ValueFromBlock integerValueResult = m_out.anchor(integerValue); 2275 2276 LValue realPart = m_out.doubleSub(integerValue, value); 2277 2278 m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation)); 2279 2280 LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation); 2281 LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1)); 2282 ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown); 2283 m_out.jump(continuation); 2284 m_out.appendTo(continuation, lastNext); 2285 2286 result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult); 2287 } 2288 2289 if (producesInteger(m_node->arithRoundingMode())) { 2290 LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())); 2291 setInt32(integerValue); 2292 } else 2293 setDouble(result); 2294 } 2295 2296 void compileArithFloor() 2297 { 2298 LValue value = lowDouble(m_node->child1()); 2299 LValue integerValue = m_out.doubleFloor(value); 2300 if (producesInteger(m_node->arithRoundingMode())) 2301 setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode()))); 2302 else 2303 setDouble(integerValue); 2304 } 2305 2306 void compileArithCeil() 2307 { 2308 LValue value = lowDouble(m_node->child1()); 2309 LValue integerValue = m_out.doubleCeil(value); 2310 if (producesInteger(m_node->arithRoundingMode())) 2311 setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode()))); 2312 else 2313 setDouble(integerValue); 2323 if (producesInteger(m_node->arithRoundingMode())) 2324 setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode()))); 2325 else 2326 setDouble(integerValue); 2327 return; 2328 } 2329 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); 2330 LValue argument = lowJSValue(m_node->child1()); 2331 setJSValue(vmCall(Int64, m_out.operation(operationArithCeil), m_callFrame, argument)); 2314 2332 } 2315 2333 2316 2334 void compileArithTrunc() 2317 2335 { 2318 LValue value = lowDouble(m_node->child1()); 2319 LValue result = m_out.doubleTrunc(value); 2320 if (producesInteger(m_node->arithRoundingMode())) 2321 setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()))); 2322 else 2323 setDouble(result); 2336 if (m_node->child1().useKind() == DoubleRepUse) { 2337 LValue value = lowDouble(m_node->child1()); 2338 LValue result = m_out.doubleTrunc(value); 2339 if (producesInteger(m_node->arithRoundingMode())) 2340 setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()))); 2341 else 2342 setDouble(result); 2343 return; 2344 } 2345 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); 2346 LValue argument = lowJSValue(m_node->child1()); 2347 setJSValue(vmCall(Int64, m_out.operation(operationArithTrunc), m_callFrame, argument)); 2324 2348 } 2325 2349 -
trunk/Source/JavaScriptCore/jsc.cpp
r206065 r206134 53 53 #include "JSWASMModule.h" 54 54 #include "LLIntData.h" 55 #include "ObjectConstructor.h" 55 56 #include "ParserError.h" 56 57 #include "ProfilerDatabase.h" … … 69 70 #include <string.h> 70 71 #include <thread> 72 #include <type_traits> 71 73 #include <wtf/CurrentTime.h> 72 74 #include <wtf/MainThread.h> … … 613 615 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*); 614 616 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*); 617 static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*); 615 618 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*); 616 619 static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*); … … 818 821 addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1); 819 822 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1); 823 addFunction(vm, "jscOptions", functionJSCOptions, 0); 820 824 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1); 821 825 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1); … … 1716 1720 } 1717 1721 1722 template<typename ValueType> 1723 typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { } 1724 1725 template<typename ValueType> 1726 typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, Identifier identifier, ValueType value) 1727 { 1728 optionsObject->putDirect(vm, identifier, JSValue(value)); 1729 } 1730 1731 EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState* exec) 1732 { 1733 JSObject* optionsObject = constructEmptyObject(exec); 1734 #define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \ 1735 addOption(exec->vm(), optionsObject, Identifier::fromString(exec, #name_), Options::name_()); 1736 JSC_OPTIONS(FOR_EACH_OPTION) 1737 #undef FOR_EACH_OPTION 1738 return JSValue::encode(optionsObject); 1739 } 1740 1718 1741 EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec) 1719 1742 {
Note: See TracChangeset
for help on using the changeset viewer.