Changeset 242715 in webkit
- Timestamp:
- Mar 11, 2019 10:21:41 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r242699 r242715 1 2019-03-11 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement "~" unary operation 4 https://bugs.webkit.org/show_bug.cgi?id=182216 5 6 Reviewed by Keith Miller. 7 8 * stress/big-int-bit-not-general.js: Added. 9 * stress/big-int-bitwise-not-jit.js: Added. 10 * stress/big-int-bitwise-not-wrapped-value.js: Added. 11 * stress/bit-op-with-object-returning-int32.js: 12 * stress/bitwise-not-fixup-rules.js: Added. 13 * stress/value-bit-not-ai-rule.js: Added. 14 1 15 2019-03-10 Ross Kirsling <ross.kirsling@sony.com> 2 16 -
trunk/JSTests/stress/bit-op-with-object-returning-int32.js
r239982 r242715 37 37 assert(numberOfDFGCompiles(bitXor) <= 1, true); 38 38 39 function bitNot(a) { 40 return ~a; 41 } 42 noInline(bitNot); 43 44 for (var i = 0; i < 10000; i++) 45 assert(bitNot(o), -14); 46 47 assert(numberOfDFGCompiles(bitNot) <= 1, true); 48 -
trunk/PerformanceTests/ChangeLog
r242373 r242715 1 2019-03-11 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement "~" unary operation 4 https://bugs.webkit.org/show_bug.cgi?id=182216 5 6 Reviewed by Keith Miller. 7 8 * BigIntBench/big-int-simple-bit-not.js: Added. 9 1 10 2019-03-04 Saam Barati <sbarati@apple.com> 2 11 -
trunk/Source/JavaScriptCore/ChangeLog
r242713 r242715 1 2019-03-11 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement "~" unary operation 4 https://bugs.webkit.org/show_bug.cgi?id=182216 5 6 Reviewed by Keith Miller. 7 8 This patch is adding support of BigInt into op_bitnot operations. In 9 addition, we are changing ArithBitNot to handle only Number operands, 10 while introducing a new node named ValueBitNot to handle Untyped and 11 BigInt. This node follows the same approach we are doing into other 12 arithimetic operations into DFG. 13 14 * dfg/DFGAbstractInterpreterInlines.h: 15 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 16 17 It is possible that fixup and prediction propagation don't convert a 18 ValueBitNot(ConstInt32) into ArithBitNot(ConstInt32) because these 19 analysis are conservative. In such case, we are adding constant 20 folding rules to ValueBitNot AI. 21 22 * dfg/DFGBackwardsPropagationPhase.cpp: 23 (JSC::DFG::BackwardsPropagationPhase::propagate): 24 25 ValueBitNot has same rules as ArithBitNot on backwards propagation. 26 27 * dfg/DFGByteCodeParser.cpp: 28 (JSC::DFG::ByteCodeParser::parseBlock): 29 30 We can emit ArithBitNot if we know that operand of op_bitnot is a 31 Number or any int. Otherwise we fallback to ValueBitNot and rely on 32 fixup to convert the node to ArithBitNot when it is possible. 33 ValueBitNot uses heap prediction on prediction propagation and we 34 collect its type from op_bitnot's value profiler. 35 36 * dfg/DFGClobberize.h: 37 (JSC::DFG::clobberize): 38 39 When we have the case with ValueBitNot(BigInt), we don't clobberize 40 world. 41 42 * dfg/DFGDoesGC.cpp: 43 (JSC::DFG::doesGC): 44 45 ValueBitNot can GC on BigIntUse because, right now, all bitNot 46 operation allocates temporary BigInts to perform calculations and it 47 can potentially trigger GC. 48 49 * dfg/DFGFixupPhase.cpp: 50 (JSC::DFG::FixupPhase::fixupNode): 51 52 ValueBitNot is responsible do handle BigIntUse and UntypedUse. To all 53 other uses, we fallback to ArithBitNot. 54 55 * dfg/DFGNode.h: 56 (JSC::DFG::Node::hasHeapPrediction): 57 * dfg/DFGNodeType.h: 58 * dfg/DFGOperations.cpp: 59 (JSC::DFG::bitwiseBinaryOp): 60 61 This template function is abstracting the new semantics of numeric 62 values operations on bitwise operations. These operations usually 63 folow these steps: 64 65 1. rhsNumeric = GetInt32OrBigInt(rhs) 66 2. lhsNumeric = GetInt32OrBigInt(lhs) 67 3. trhow error if TypeOf(rhsNumeric) != TypeOf(lhsNumeric) 68 4. return BigInt::bitwiseOp(bitOp, rhs, lhs) if TypeOf(lhsNumeric) == BigInt 69 5. return rhs <int32BitOp> lhs 70 71 Since we have almost the same code for every bitwise op, 72 we use such template to avoid code duplication. The template receives 73 Int32 and BigInt operations as parameter. Error message is received as 74 `const char*` instead of `String&` to avoid String allocation even when 75 there is no error to throw. 76 77 * dfg/DFGOperations.h: 78 * dfg/DFGPredictionPropagationPhase.cpp: 79 * dfg/DFGSafeToExecute.h: 80 (JSC::DFG::safeToExecute): 81 * dfg/DFGSpeculativeJIT.cpp: 82 (JSC::DFG::SpeculativeJIT::compileValueBitNot): 83 84 ValueBitNot generates speculative code for BigIntUse and this code is a 85 call to `operationBitNotBigInt`. This operation is faster than 86 `operationValueBitNot` because there is no need to check types of 87 operands and execute properly operation. We still need to check 88 exceptions after `operationBitNotBigInt` because it can throw OOM. 89 90 (JSC::DFG::SpeculativeJIT::compileBitwiseNot): 91 * dfg/DFGSpeculativeJIT.h: 92 * dfg/DFGSpeculativeJIT32_64.cpp: 93 (JSC::DFG::SpeculativeJIT::compile): 94 * dfg/DFGSpeculativeJIT64.cpp: 95 (JSC::DFG::SpeculativeJIT::compile): 96 * ftl/FTLCapabilities.cpp: 97 (JSC::FTL::canCompile): 98 * ftl/FTLLowerDFGToB3.cpp: 99 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 100 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitNot): 101 (JSC::FTL::DFG::LowerDFGToB3::compileArithBitNot): 102 * runtime/CommonSlowPaths.cpp: 103 (JSC::SLOW_PATH_DECL): 104 * runtime/JSBigInt.cpp: 105 (JSC::JSBigInt::bitwiseNot): 106 * runtime/JSBigInt.h: 107 1 108 2019-03-11 Darin Adler <darin@apple.com> 2 109 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r242655 r242715 377 377 } 378 378 379 case ValueBitNot: { 380 JSValue operand = forNode(node->child1()).value(); 381 if (operand && operand.isInt32()) { 382 didFoldClobberWorld(); 383 int32_t a = operand.asInt32(); 384 setConstant(node, JSValue(~a)); 385 break; 386 } 387 388 if (node->child1().useKind() == BigIntUse) 389 setTypeForNode(node, SpecBigInt); 390 else { 391 clobberWorld(); 392 setTypeForNode(node, SpecBoolInt32 | SpecBigInt); 393 } 394 395 break; 396 } 397 379 398 case ArithBitNot: { 380 if (node->child1().useKind() == UntypedUse) {381 clobberWorld();382 setNonCellTypeForNode(node, SpecInt32Only);383 break;384 }385 386 399 JSValue operand = forNode(node->child1()).value(); 387 400 if (operand && operand.isInt32()) { -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r240269 r242715 211 211 break; 212 212 213 case ValueBitNot: 213 214 case ArithBitNot: { 214 215 flags |= NodeBytecodeUsesAsInt; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r242015 r242715 4919 4919 case op_bitnot: { 4920 4920 auto bytecode = currentInstruction->as<OpBitnot>(); 4921 SpeculatedType prediction = getPrediction(); 4921 4922 Node* op1 = get(bytecode.m_operand); 4922 set(bytecode.m_dst, addToGraph(ArithBitNot, op1)); 4923 if (op1->hasNumberOrAnyIntResult()) 4924 set(bytecode.m_dst, addToGraph(ArithBitNot, op1)); 4925 else 4926 set(bytecode.m_dst, addToGraph(ValueBitNot, OpInfo(), OpInfo(prediction), op1)); 4923 4927 NEXT_OPCODE(op_bitnot); 4924 4928 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r241228 r242715 260 260 return; 261 261 262 case ValueBitNot: 263 if (node->child1().useKind() == BigIntUse) { 264 def(PureValue(node)); 265 return; 266 } 267 read(World); 268 write(Heap); 269 return; 270 262 271 case ArithBitNot: 263 272 if (node->child1().useKind() == UntypedUse) { -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r241772 r242715 379 379 case ValueMul: 380 380 case ValueDiv: 381 case ValueBitNot: 381 382 case ValueNegate: 382 383 #else -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r241228 r242715 235 235 } 236 236 237 case ValueBitNot: { 238 Edge& operandEdge = node->child1(); 239 240 if (operandEdge.node()->shouldSpeculateBigInt()) { 241 node->clearFlags(NodeMustGenerate); 242 fixEdge<BigIntUse>(operandEdge); 243 } else if (operandEdge.node()->shouldSpeculateUntypedForBitOps()) 244 fixEdge<UntypedUse>(operandEdge); 245 else { 246 node->setOp(ArithBitNot); 247 node->setResult(NodeResultInt32); 248 node->clearFlags(NodeMustGenerate); 249 fixIntConvertingEdge(operandEdge); 250 } 251 break; 252 } 253 237 254 case ArithBitNot: { 238 if (node->child1().node()->shouldSpeculateUntypedForBitOps()) { 239 fixEdge<UntypedUse>(node->child1()); 240 break; 241 } 242 243 fixIntConvertingEdge(node->child1()); 244 node->clearFlags(NodeMustGenerate); 255 Edge& operandEdge = node->child1(); 256 257 fixIntConvertingEdge(operandEdge); 245 258 break; 246 259 } -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r240938 r242715 1694 1694 case ValueBitOr: 1695 1695 case ValueBitXor: 1696 case ValueBitNot: 1696 1697 case CallObjectConstructor: 1697 1698 case LoadKeyFromMapBucket: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r241228 r242715 112 112 \ 113 113 /* Nodes for bitwise operations. */\ 114 macro(ArithBitNot, NodeResultInt32 | NodeMustGenerate) \ 114 macro(ValueBitNot, NodeResultJS | NodeMustGenerate) \ 115 macro(ArithBitNot, NodeResultInt32) \ 115 116 macro(ValueBitAnd, NodeResultJS | NodeMustGenerate) \ 116 117 macro(ArithBitAnd, NodeResultInt32) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r242500 r242715 214 214 } 215 215 216 template<typename BigIntOperation, typename Int32Operation> 217 static ALWAYS_INLINE EncodedJSValue bitwiseBinaryOp(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, Int32Operation&& int32Op, 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.toBigIntOrInt32(exec); 227 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 228 auto rightNumeric = op2.toBigIntOrInt32(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(int32Op(WTF::get<int32_t>(leftNumeric), WTF::get<int32_t>(rightNumeric)))); 241 } 242 216 243 static ALWAYS_INLINE EncodedJSValue parseIntResult(double input) 217 244 { … … 362 389 JSValue op1 = JSValue::decode(encodedOp1); 363 390 364 int32_t operandValue = op1.toInt32(exec);391 auto operandNumeric = op1.toBigIntOrInt32(exec); 365 392 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 366 393 367 return JSValue::encode(jsNumber(~operandValue)); 394 if (WTF::holds_alternative<JSBigInt*>(operandNumeric)) 395 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::bitwiseNot(exec, WTF::get<JSBigInt*>(operandNumeric)))); 396 397 return JSValue::encode(jsNumber(~WTF::get<int32_t>(operandNumeric))); 368 398 } 369 399 370 400 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 371 401 { 372 VM* vm = &exec->vm(); 373 NativeCallFrameTracer tracer(vm, exec); 374 auto scope = DECLARE_THROW_SCOPE(*vm); 375 376 JSValue op1 = JSValue::decode(encodedOp1); 377 JSValue op2 = JSValue::decode(encodedOp2); 378 379 auto leftNumeric = op1.toBigIntOrInt32(exec); 380 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 381 auto rightNumeric = op2.toBigIntOrInt32(exec); 382 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 383 384 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 385 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 386 JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 387 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 388 return JSValue::encode(result); 389 } 390 391 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise 'and' operation."); 392 } 393 394 return JSValue::encode(jsNumber(WTF::get<int32_t>(leftNumeric) & WTF::get<int32_t>(rightNumeric))); 402 auto bigIntOp = [] (ExecState* exec, JSBigInt* left, JSBigInt* right) -> JSBigInt* { 403 return JSBigInt::bitwiseAnd(exec, left, right); 404 }; 405 406 auto int32Op = [] (int32_t left, int32_t right) -> int32_t { 407 return left & right; 408 }; 409 410 return bitwiseBinaryOp(exec, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'and' operation."_s); 395 411 } 396 412 397 413 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 398 414 { 399 VM* vm = &exec->vm(); 400 NativeCallFrameTracer tracer(vm, exec); 401 auto scope = DECLARE_THROW_SCOPE(*vm); 402 403 JSValue op1 = JSValue::decode(encodedOp1); 404 JSValue op2 = JSValue::decode(encodedOp2); 405 406 auto leftNumeric = op1.toBigIntOrInt32(exec); 407 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 408 auto rightNumeric = op2.toBigIntOrInt32(exec); 409 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 410 411 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 412 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 413 JSBigInt* result = JSBigInt::bitwiseOr(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 414 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 415 return JSValue::encode(result); 416 } 417 418 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise 'or' operation."); 419 } 420 421 return JSValue::encode(jsNumber(WTF::get<int32_t>(leftNumeric) | WTF::get<int32_t>(rightNumeric))); 415 auto bigIntOp = [] (ExecState* exec, JSBigInt* left, JSBigInt* right) -> JSBigInt* { 416 return JSBigInt::bitwiseOr(exec, left, right); 417 }; 418 419 auto int32Op = [] (int32_t left, int32_t right) -> int32_t { 420 return left | right; 421 }; 422 423 return bitwiseBinaryOp(exec, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'or' operation."_s); 422 424 } 423 425 424 426 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 425 427 { 426 VM* vm = &exec->vm(); 427 NativeCallFrameTracer tracer(vm, exec); 428 auto scope = DECLARE_THROW_SCOPE(*vm); 429 430 JSValue op1 = JSValue::decode(encodedOp1); 431 JSValue op2 = JSValue::decode(encodedOp2); 432 433 auto leftNumeric = op1.toBigIntOrInt32(exec); 434 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 435 auto rightNumeric = op2.toBigIntOrInt32(exec); 436 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 437 438 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 439 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 440 JSBigInt* result = JSBigInt::bitwiseXor(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 441 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 442 return JSValue::encode(result); 443 } 444 445 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise 'xor' operation."); 446 } 447 448 return JSValue::encode(jsNumber(WTF::get<int32_t>(leftNumeric) ^ WTF::get<int32_t>(rightNumeric))); 428 auto bigIntOp = [] (ExecState* exec, JSBigInt* left, JSBigInt* right) -> JSBigInt* { 429 return JSBigInt::bitwiseXor(exec, left, right); 430 }; 431 432 auto int32Op = [] (int32_t left, int32_t right) -> int32_t { 433 return left ^ right; 434 }; 435 436 return bitwiseBinaryOp(exec, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'xor' operation."_s); 449 437 } 450 438 … … 1337 1325 1338 1326 return JSBigInt::sub(exec, leftOperand, rightOperand); 1327 } 1328 1329 JSCell* JIT_OPERATION operationBitNotBigInt(ExecState* exec, JSCell* op1) 1330 { 1331 VM* vm = &exec->vm(); 1332 NativeCallFrameTracer tracer(vm, exec); 1333 1334 JSBigInt* operand = jsCast<JSBigInt*>(op1); 1335 1336 return JSBigInt::bitwiseNot(exec, operand); 1339 1337 } 1340 1338 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r242252 r242715 171 171 JSCell* JIT_OPERATION operationDivBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 172 172 JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 173 JSCell* JIT_OPERATION operationBitNotBigInt(ExecState*, JSCell* op1) WTF_INTERNAL; 173 174 JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 174 175 JSCell* JIT_OPERATION operationAddBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r240327 r242715 803 803 case ValueBitXor: 804 804 case ValueBitOr: 805 case ValueBitNot: 805 806 case CallObjectConstructor: 806 807 case GetArgument: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r240327 r242715 232 232 case ValueBitXor: 233 233 case ValueBitOr: 234 case ValueBitNot: 234 235 case ValueNegate: 235 236 case ValueAdd: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r242626 r242715 3523 3523 } 3524 3524 3525 void SpeculativeJIT::compileValueBitNot(Node* node) 3526 { 3527 Edge& child1 = node->child1(); 3528 3529 if (child1.useKind() == BigIntUse) { 3530 SpeculateCellOperand operand(this, child1); 3531 GPRReg operandGPR = operand.gpr(); 3532 3533 speculateBigInt(child1, operandGPR); 3534 3535 flushRegisters(); 3536 GPRFlushedCallResult result(this); 3537 GPRReg resultGPR = result.gpr(); 3538 3539 callOperation(operationBitNotBigInt, resultGPR, operandGPR); 3540 m_jit.exceptionCheck(); 3541 cellResult(resultGPR, node); 3542 3543 return; 3544 } 3545 3546 JSValueOperand operand(this, child1); 3547 JSValueRegs operandRegs = operand.jsValueRegs(); 3548 3549 flushRegisters(); 3550 JSValueRegsFlushedCallResult result(this); 3551 JSValueRegs resultRegs = result.regs(); 3552 callOperation(operationValueBitNot, resultRegs, operandRegs); 3553 m_jit.exceptionCheck(); 3554 3555 jsValueResult(resultRegs, node); 3556 } 3557 3525 3558 void SpeculativeJIT::compileBitwiseNot(Node* node) 3526 3559 { 3527 3560 Edge& child1 = node->child1(); 3528 3529 if (child1.useKind() == UntypedUse) {3530 JSValueOperand operand(this, child1);3531 JSValueRegs operandRegs = operand.jsValueRegs();3532 3533 flushRegisters();3534 JSValueRegsFlushedCallResult result(this);3535 JSValueRegs resultRegs = result.regs();3536 callOperation(operationValueBitNot, resultRegs, operandRegs);3537 m_jit.exceptionCheck();3538 3539 jsValueResult(resultRegs, node);3540 return;3541 }3542 3561 3543 3562 SpeculateInt32Operand operand(this, child1); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r242397 r242715 1326 1326 void compileDoubleAsInt32(Node*); 1327 1327 1328 void compileValueBitNot(Node*); 1328 1329 void compileBitwiseNot(Node*); 1329 1330 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r242286 r242715 1990 1990 case ArithBitXor: 1991 1991 compileBitwiseOp(node); 1992 break; 1993 1994 case ValueBitNot: 1995 compileValueBitNot(node); 1992 1996 break; 1993 1997 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r242286 r242715 2079 2079 // the argument is not used. 2080 2080 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat())); 2081 break; 2082 2083 case ValueBitNot: 2084 compileValueBitNot(node); 2081 2085 break; 2082 2086 -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r241222 r242715 92 92 case ValueBitXor: 93 93 case ValueBitOr: 94 case ValueBitNot: 94 95 case ValueNegate: 95 96 case ValueAdd: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r242626 r242715 666 666 compileArithUnary(); 667 667 break; 668 case ValueBitNot: 669 compileValueBitNot(); 670 break; 668 671 case ArithBitNot: 669 672 compileArithBitNot(); … … 2891 2894 } 2892 2895 2896 void compileValueBitNot() 2897 { 2898 if (m_node->child1().useKind() == BigIntUse) { 2899 LValue operand = lowBigInt(m_node->child1()); 2900 LValue result = vmCall(pointerType(), m_out.operation(operationBitNotBigInt), m_callFrame, operand); 2901 setJSValue(result); 2902 return; 2903 } 2904 2905 LValue operand = lowJSValue(m_node->child1()); 2906 LValue result = vmCall(Int64, m_out.operation(operationValueBitNot), m_callFrame, operand); 2907 setJSValue(result); 2908 } 2909 2893 2910 void compileArithBitNot() 2894 2911 { 2895 if (m_node->child1().useKind() == UntypedUse) {2896 LValue operand = lowJSValue(m_node->child1());2897 LValue result = vmCall(Int64, m_out.operation(operationValueBitNot), m_callFrame, operand);2898 setJSValue(result);2899 return;2900 }2901 2902 2912 setInt32(m_out.bitNot(lowInt32(m_node->child1()))); 2903 2913 } -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r242500 r242715 716 716 BEGIN(); 717 717 auto bytecode = pc->as<OpBitnot>(); 718 int32_t operand = GET_C(bytecode.m_operand).jsValue().toInt32(exec); 719 CHECK_EXCEPTION(); 720 RETURN_PROFILED(jsNumber(~operand)); 718 auto operandNumeric = GET_C(bytecode.m_operand).jsValue().toBigIntOrInt32(exec); 719 CHECK_EXCEPTION(); 720 721 if (WTF::holds_alternative<JSBigInt*>(operandNumeric)) { 722 JSBigInt* result = JSBigInt::bitwiseNot(exec, WTF::get<JSBigInt*>(operandNumeric)); 723 CHECK_EXCEPTION(); 724 RETURN_PROFILED(result); 725 } 726 727 RETURN_PROFILED(jsNumber(~WTF::get<int32_t>(operandNumeric))); 721 728 } 722 729 -
trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp
r240255 r242715 526 526 } 527 527 528 JSBigInt* JSBigInt::bitwiseNot(ExecState* exec, JSBigInt* x) 529 { 530 if (x->sign()) { 531 // ~(-x) == ~(~(x-1)) == x-1 532 return absoluteSubOne(exec, x, x->length()); 533 } 534 // ~x == -x-1 == -(x+1) 535 return absoluteAddOne(exec, x, SignOption::Signed); 536 } 537 528 538 #if USE(JSVALUE32_64) 529 539 #define HAVE_TWO_DIGIT 1 -
trunk/Source/JavaScriptCore/runtime/JSBigInt.h
r242109 r242715 125 125 static JSBigInt* bitwiseOr(ExecState*, JSBigInt* x, JSBigInt* y); 126 126 static JSBigInt* bitwiseXor(ExecState*, JSBigInt* x, JSBigInt* y); 127 static JSBigInt* bitwiseNot(ExecState*, JSBigInt* x); 127 128 128 129 static JSBigInt* leftShift(ExecState*, JSBigInt* x, JSBigInt* y);
Note: See TracChangeset
for help on using the changeset viewer.