Changeset 236901 in webkit
- Timestamp:
- Oct 6, 2018 5:20:59 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 7 added
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r236872 r236901 1 2018-10-06 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement support for "|" 4 https://bugs.webkit.org/show_bug.cgi?id=186229 5 6 Reviewed by Yusuke Suzuki. 7 8 * stress/big-int-bitwise-and-jit.js: 9 * stress/big-int-bitwise-or-general.js: Added. 10 * stress/big-int-bitwise-or-jit-untyped.js: Added. 11 * stress/big-int-bitwise-or-jit.js: Added. 12 * stress/big-int-bitwise-or-memory-stress.js: Added. 13 * stress/big-int-bitwise-or-to-primitive-precedence.js: Added. 14 * stress/big-int-bitwise-or-type-error.js: Added. 15 * stress/big-int-bitwise-or-wrapped-value.js: Added. 16 1 17 2018-10-05 Dominik Infuehr <dominik.infuehr@gmail.com> 2 18 -
trunk/JSTests/stress/big-int-bitwise-and-jit.js
r236637 r236901 10 10 function bigIntBitAnd(a, b) { 11 11 return (a & b) & (a & 0b11n); 12 13 12 } 14 13 noInline(bigIntBitAnd); -
trunk/Source/JavaScriptCore/ChangeLog
r236900 r236901 1 2018-10-06 Caio Lima <ticaiolima@gmail.com> 2 3 [ESNext][BigInt] Implement support for "|" 4 https://bugs.webkit.org/show_bug.cgi?id=186229 5 6 Reviewed by Yusuke Suzuki. 7 8 This patch is introducing support for BigInt into bitwise "or" operator. 9 In addition, we are also introducing 2 new DFG nodes, named "ArithBitOr" and 10 "ValueBitOr", to replace "BitOr" node. The idea is to follow the 11 difference that we make on Arith<op> and Value<op>, where ArithBitOr 12 handles cases when the operands are Int32 and ValueBitOr handles 13 the remaining cases. 14 15 We are also changing op_bitor to use ValueProfile. We are using 16 ValueProfile during DFG generation to emit "ArithBitOr" when 17 outcome prediction is Int32. 18 19 * bytecode/CodeBlock.cpp: 20 (JSC::CodeBlock::finishCreation): 21 (JSC::CodeBlock::arithProfileForPC): 22 * bytecompiler/BytecodeGenerator.cpp: 23 (JSC::BytecodeGenerator::emitBinaryOp): 24 * dfg/DFGAbstractInterpreterInlines.h: 25 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 26 * dfg/DFGBackwardsPropagationPhase.cpp: 27 (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo): 28 (JSC::DFG::BackwardsPropagationPhase::propagate): 29 * dfg/DFGByteCodeParser.cpp: 30 (JSC::DFG::ByteCodeParser::parseBlock): 31 * dfg/DFGClobberize.h: 32 (JSC::DFG::clobberize): 33 * dfg/DFGDoesGC.cpp: 34 (JSC::DFG::doesGC): 35 * dfg/DFGFixupPhase.cpp: 36 (JSC::DFG::FixupPhase::fixupNode): 37 * dfg/DFGNodeType.h: 38 * dfg/DFGOperations.cpp: 39 (JSC::DFG::bitwiseOp): 40 * dfg/DFGOperations.h: 41 * dfg/DFGPredictionPropagationPhase.cpp: 42 * dfg/DFGSafeToExecute.h: 43 (JSC::DFG::safeToExecute): 44 * dfg/DFGSpeculativeJIT.cpp: 45 (JSC::DFG::SpeculativeJIT::compileValueBitwiseOp): 46 (JSC::DFG::SpeculativeJIT::compileBitwiseOp): 47 * dfg/DFGSpeculativeJIT.h: 48 (JSC::DFG::SpeculativeJIT::bitOp): 49 * dfg/DFGSpeculativeJIT32_64.cpp: 50 (JSC::DFG::SpeculativeJIT::compile): 51 * dfg/DFGSpeculativeJIT64.cpp: 52 (JSC::DFG::SpeculativeJIT::compile): 53 * dfg/DFGStrengthReductionPhase.cpp: 54 (JSC::DFG::StrengthReductionPhase::handleNode): 55 * ftl/FTLCapabilities.cpp: 56 (JSC::FTL::canCompile): 57 * ftl/FTLLowerDFGToB3.cpp: 58 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 59 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitOr): 60 (JSC::FTL::DFG::LowerDFGToB3::compileArithBitOr): 61 (JSC::FTL::DFG::LowerDFGToB3::compileBitOr): Deleted. 62 * jit/JITArithmetic.cpp: 63 (JSC::JIT::emit_op_bitor): 64 * llint/LowLevelInterpreter32_64.asm: 65 * llint/LowLevelInterpreter64.asm: 66 * runtime/CommonSlowPaths.cpp: 67 (JSC::SLOW_PATH_DECL): 68 * runtime/JSBigInt.cpp: 69 (JSC::JSBigInt::bitwiseAnd): 70 (JSC::JSBigInt::bitwiseOr): 71 (JSC::JSBigInt::absoluteBitwiseOp): 72 (JSC::JSBigInt::absoluteAddOne): 73 * runtime/JSBigInt.h: 74 1 75 2018-10-05 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 76 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r236637 r236901 583 583 584 584 case op_bitand: 585 case op_bitor: 585 586 case op_to_this: { 586 587 linkValueProfile(i, opLength); … … 2936 2937 case op_negate: 2937 2938 return bitwise_cast<ArithProfile*>(&pc[3].u.operand); 2938 case op_bitor:2939 case op_bitand:2940 2939 case op_bitxor: 2941 2940 case op_add: -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r236637 r236901 1734 1734 { 1735 1735 1736 if (opcodeID == op_bitand ) {1736 if (opcodeID == op_bitand || opcodeID == op_bitor) { 1737 1737 UnlinkedValueProfile profile = emitProfiledOpcode(opcodeID); 1738 1738 instructions().append(dst->index()); … … 1748 1748 instructions().append(src2->index()); 1749 1749 1750 if (opcodeID == op_bit or || opcodeID == op_bitxor||1751 opcodeID == op_ add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)1750 if (opcodeID == op_bitxor || opcodeID == op_add || 1751 opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div) 1752 1752 instructions().append(ArithProfile(types.first(), types.second()).bits()); 1753 1753 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r236637 r236901 376 376 } 377 377 378 case ValueBitOr: 378 379 case ValueBitAnd: 379 380 clobberWorld(); 380 setTypeForNode(node, SpecBoolInt32 | SpecBigInt); 381 if (node->binaryUseKind() == BigIntUse) 382 setTypeForNode(node, SpecBigInt); 383 else 384 setTypeForNode(node, SpecBoolInt32 | SpecBigInt); 381 385 break; 382 386 383 387 case ArithBitAnd: 384 case BitOr:388 case ArithBitOr: 385 389 case BitXor: 386 390 case BitRShift: … … 402 406 setConstant(node, JSValue(a & b)); 403 407 break; 404 case BitOr:408 case ArithBitOr: 405 409 setConstant(node, JSValue(a | b)); 406 410 break; -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r236637 r236901 119 119 } 120 120 121 case BitOr:121 case ArithBitOr: 122 122 case BitXor: 123 123 case BitLShift: { … … 209 209 210 210 case ArithBitAnd: 211 case BitOr:211 case ArithBitOr: 212 212 case BitXor: 213 213 case BitRShift: -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r236637 r236901 4857 4857 Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand)); 4858 4858 Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand)); 4859 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitOr, op1, op2)); 4859 if (isInt32Speculation(getPrediction())) 4860 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ArithBitOr, op1, op2)); 4861 else 4862 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ValueBitOr, op1, op2)); 4860 4863 NEXT_OPCODE(op_bitor); 4861 4864 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r236637 r236901 264 264 265 265 case ArithBitAnd: 266 case BitOr:266 case ArithBitOr: 267 267 case BitXor: 268 268 case BitLShift: … … 637 637 case HasOwnProperty: 638 638 case ValueBitAnd: 639 case ValueBitOr: 639 640 case ValueNegate: 640 641 case ValueAdd: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r236637 r236901 69 69 case SetArgument: 70 70 case ArithBitAnd: 71 case BitOr:71 case ArithBitOr: 72 72 case BitXor: 73 73 case BitLShift: … … 98 98 case ArithUnary: 99 99 case ValueBitAnd: 100 case ValueBitOr: 100 101 case ValueAdd: 101 102 case ValueNegate: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r236637 r236901 100 100 } 101 101 102 case ValueBitOr: 102 103 case ValueBitAnd: { 103 104 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) { … … 112 113 } 113 114 115 case ArithBitOr: 114 116 case ArithBitAnd: { 115 117 if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) { 116 118 fixEdge<UntypedUse>(node->child1()); 117 119 fixEdge<UntypedUse>(node->child2()); 118 node->setOpAndDefaultFlags(ValueBitAnd); 120 121 switch (op) { 122 case ArithBitOr: 123 node->setOpAndDefaultFlags(ValueBitOr); 124 break; 125 case ArithBitAnd: 126 node->setOpAndDefaultFlags(ValueBitAnd); 127 break; 128 default: 129 DFG_CRASH(m_graph, node, "Unexpected node during ArithBit operation fixup"); 130 break; 131 } 132 119 133 break; 120 134 } … … 124 138 } 125 139 126 case BitOr:127 140 case BitXor: 128 141 case BitRShift: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r236637 r236901 114 114 macro(ValueBitAnd, NodeResultJS | NodeMustGenerate) \ 115 115 macro(ArithBitAnd, NodeResultInt32) \ 116 macro(BitOr, NodeResultInt32) \ 116 macro(ValueBitOr, NodeResultJS | NodeMustGenerate) \ 117 macro(ArithBitOr, NodeResultInt32) \ 117 118 macro(BitXor, NodeResultInt32) \ 118 119 macro(BitLShift, NodeResultInt32) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r236697 r236901 355 355 } 356 356 357 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise andoperation.");357 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise 'and' operation."); 358 358 } 359 359 … … 370 370 JSValue op2 = JSValue::decode(encodedOp2); 371 371 372 int32_t a = op1.toInt32(exec);372 auto leftNumeric = op1.toBigIntOrInt32(exec); 373 373 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 374 scope.release(); 375 int32_t b = op2.toInt32(exec); 376 return JSValue::encode(jsNumber(a | b)); 374 auto rightNumeric = op2.toBigIntOrInt32(exec); 375 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 376 377 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 378 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 379 JSBigInt* result = JSBigInt::bitwiseOr(*vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 380 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 381 return JSValue::encode(result); 382 } 383 384 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise 'or' operation."); 385 } 386 387 return JSValue::encode(jsNumber(WTF::get<int32_t>(leftNumeric) | WTF::get<int32_t>(rightNumeric))); 377 388 } 378 389 … … 1285 1296 1286 1297 return JSBigInt::bitwiseAnd(*vm, leftOperand, rightOperand); 1298 } 1299 1300 JSCell* JIT_OPERATION operationBitOrBigInt(ExecState* exec, JSCell* op1, JSCell* op2) 1301 { 1302 VM* vm = &exec->vm(); 1303 NativeCallFrameTracer tracer(vm, exec); 1304 1305 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1); 1306 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); 1307 1308 return JSBigInt::bitwiseOr(*vm, leftOperand, rightOperand); 1287 1309 } 1288 1310 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r236637 r236901 165 165 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 166 166 JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 167 JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; 167 168 size_t JIT_OPERATION operationSameValue(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL; 168 169 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState*, Structure*, JSScope*, SymbolTable*, EncodedJSValue); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r236637 r236901 247 247 } 248 248 249 case ValueBitOr: 249 250 case ValueBitAnd: { 250 251 if (node->child1()->shouldSpeculateBigInt() && node->child2()->shouldSpeculateBigInt()) … … 709 710 710 711 case ArithBitAnd: 711 case BitOr:712 case ArithBitOr: 712 713 case BitXor: 713 714 case BitRShift: … … 1064 1065 case SetLocal: 1065 1066 case UInt32ToNumber: 1067 case ValueBitOr: 1066 1068 case ValueBitAnd: 1067 1069 case ValueNegate: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r236637 r236901 199 199 case SetArgument: 200 200 case ArithBitAnd: 201 case BitOr:201 case ArithBitOr: 202 202 case BitXor: 203 203 case BitLShift: … … 228 228 case ArithUnary: 229 229 case ValueBitAnd: 230 case ValueBitOr: 230 231 case ValueNegate: 231 232 case ValueAdd: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r236734 r236901 3600 3600 emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node); 3601 3601 return; 3602 case ValueBitOr: 3603 emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node); 3604 return; 3602 3605 default: 3603 3606 RELEASE_ASSERT_NOT_REACHED(); … … 3618 3621 GPRFlushedCallResult result(this); 3619 3622 GPRReg resultGPR = result.gpr(); 3620 callOperation(operationBitAndBigInt, resultGPR, leftGPR, rightGPR); 3623 3624 switch (op) { 3625 case ValueBitAnd: 3626 callOperation(operationBitAndBigInt, resultGPR, leftGPR, rightGPR); 3627 break; 3628 case ValueBitOr: 3629 callOperation(operationBitOrBigInt, resultGPR, leftGPR, rightGPR); 3630 break; 3631 default: 3632 RELEASE_ASSERT_NOT_REACHED(); 3633 } 3634 3621 3635 m_jit.exceptionCheck(); 3622 3636 cellResult(resultGPR, node); … … 3631 3645 if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) { 3632 3646 switch (op) { 3633 case BitOr:3634 emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);3635 return;3636 3647 case BitXor: 3637 3648 emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r236637 r236901 637 637 m_jit.and32(Imm32(imm), op1, result); 638 638 break; 639 case BitOr:639 case ArithBitOr: 640 640 m_jit.or32(Imm32(imm), op1, result); 641 641 break; … … 653 653 m_jit.and32(op1, op2, result); 654 654 break; 655 case BitOr:655 case ArithBitOr: 656 656 m_jit.or32(op1, op2, result); 657 657 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r236734 r236901 1980 1980 break; 1981 1981 1982 case ValueBitOr: 1982 1983 case ValueBitAnd: 1983 1984 compileValueBitwiseOp(node); … … 1985 1986 1986 1987 case ArithBitAnd: 1987 case BitOr:1988 case ArithBitOr: 1988 1989 case BitXor: 1989 1990 compileBitwiseOp(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r236734 r236901 2076 2076 2077 2077 case ValueBitAnd: 2078 case ValueBitOr: 2078 2079 compileValueBitwiseOp(node); 2079 2080 break; 2080 2081 2081 2082 case ArithBitAnd: 2082 case BitOr:2083 case ArithBitOr: 2083 2084 case BitXor: 2084 2085 compileBitwiseOp(node); -
trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r236637 r236901 79 79 { 80 80 switch (m_node->op()) { 81 case BitOr:81 case ArithBitOr: 82 82 handleCommutativity(); 83 83 -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r236637 r236901 60 60 case Return: 61 61 case ArithBitAnd: 62 case BitOr:62 case ArithBitOr: 63 63 case BitXor: 64 64 case BitRShift: … … 88 88 case PutGlobalVariable: 89 89 case ValueBitAnd: 90 case ValueBitOr: 90 91 case ValueNegate: 91 92 case ValueAdd: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r236824 r236901 656 656 compileArithBitAnd(); 657 657 break; 658 case DFG::BitOr: 659 compileBitOr(); 658 case ValueBitOr: 659 compileValueBitOr(); 660 break; 661 case ArithBitOr: 662 compileArithBitOr(); 660 663 break; 661 664 case DFG::BitXor: … … 2829 2832 } 2830 2833 2831 void compileBitOr() 2832 { 2833 if (m_node->isBinaryUseKind(UntypedUse)) { 2834 emitBinaryBitOpSnippet<JITBitOrGenerator>(operationValueBitOr); 2835 return; 2836 } 2834 void compileValueBitOr() 2835 { 2836 if (m_node->isBinaryUseKind(BigIntUse)) { 2837 LValue left = lowBigInt(m_node->child1()); 2838 LValue right = lowBigInt(m_node->child2()); 2839 2840 LValue result = vmCall(pointerType(), m_out.operation(operationBitOrBigInt), m_callFrame, left, right); 2841 setJSValue(result); 2842 return; 2843 } 2844 2845 emitBinaryBitOpSnippet<JITBitOrGenerator>(operationValueBitOr); 2846 } 2847 2848 void compileArithBitOr() 2849 { 2837 2850 setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); 2838 2851 } -
trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp
r236637 r236901 582 582 void JIT::emit_op_bitor(Instruction* currentInstruction) 583 583 { 584 emitBitBinaryOpFastPath<JITBitOrGenerator>(currentInstruction );584 emitBitBinaryOpFastPath<JITBitOrGenerator>(currentInstruction, ProfilingPolicy::ShouldEmitProfiling); 585 585 } 586 586 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r236637 r236901 1242 1242 _llint_op_bitor: 1243 1243 traceExecution() 1244 bitOp (1244 bitOpProfiled( 1245 1245 macro (left, right) ori left, right end, 1246 1246 _slow_path_bitor, -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r236637 r236901 1185 1185 _llint_op_bitor: 1186 1186 traceExecution() 1187 bitOp (1187 bitOpProfiled( 1188 1188 macro (left, right) ori left, right end, 1189 1189 _slow_path_bitor, -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r236637 r236901 668 668 } 669 669 670 THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise andoperation."));670 THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise 'and' operation.")); 671 671 } 672 672 … … 677 677 { 678 678 BEGIN(); 679 int32_t a = OP_C(2).jsValue().toInt32(exec); 680 if (UNLIKELY(throwScope.exception())) 681 RETURN(JSValue()); 682 int32_t b = OP_C(3).jsValue().toInt32(exec); 683 RETURN(jsNumber(a | b)); 679 auto leftNumeric = OP_C(2).jsValue().toBigIntOrInt32(exec); 680 CHECK_EXCEPTION(); 681 auto rightNumeric = OP_C(3).jsValue().toBigIntOrInt32(exec); 682 CHECK_EXCEPTION(); 683 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 684 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { 685 JSBigInt* result = JSBigInt::bitwiseOr(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); 686 CHECK_EXCEPTION(); 687 RETURN_PROFILED(op_bitor, result); 688 } 689 690 THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise 'or' operation.")); 691 } 692 693 RETURN_PROFILED(op_bitor, jsNumber(WTF::get<int32_t>(leftNumeric) | WTF::get<int32_t>(rightNumeric))); 684 694 } 685 695 -
trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp
r236737 r236901 392 392 result = absoluteOr(vm, result, y1); 393 393 394 return absoluteAddOne(vm, result, true);394 return absoluteAddOne(vm, result, SignOption::Signed); 395 395 } 396 396 … … 402 402 // x & (-y) == x & ~(y-1) == x & ~(y-1) 403 403 return absoluteAndNot(vm, x, absoluteSubOne(vm, y, y->length())); 404 } 405 406 JSBigInt* JSBigInt::bitwiseOr(VM& vm, JSBigInt* x, JSBigInt* y) 407 { 408 unsigned resultLength = std::max(x->length(), y->length()); 409 410 if (!x->sign() && !y->sign()) 411 return absoluteOr(vm, x, y); 412 413 if (x->sign() && y->sign()) { 414 // (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1)) 415 // == -(((x-1) & (y-1)) + 1) 416 JSBigInt* result = absoluteSubOne(vm, x, resultLength); 417 JSBigInt* y1 = absoluteSubOne(vm, y, y->length()); 418 result = absoluteAnd(vm, result, y1); 419 return absoluteAddOne(vm, result, SignOption::Signed); 420 } 421 422 ASSERT(x->sign() != y->sign()); 423 424 // Assume that x is the positive BigInt. 425 if (x->sign()) 426 std::swap(x, y); 427 428 // x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1) 429 JSBigInt* result = absoluteSubOne(vm, y, resultLength); 430 result = absoluteAndNot(vm, result, x); 431 return absoluteAddOne(vm, result, SignOption::Signed); 404 432 } 405 433 … … 1029 1057 // v v v v 1030 1058 // result: [ 0 ][ x3 ][ r2 ][ r1 ][ r0 ] 1031 inline JSBigInt* JSBigInt::absoluteBitwiseOp(VM& vm, JSBigInt* x, JSBigInt* y, ExtraDigitsHandling extraDigits, SymmetricOp symmetric, std::function<Digit(Digit, Digit)> op) 1059 template<typename BitwiseOp> 1060 inline JSBigInt* JSBigInt::absoluteBitwiseOp(VM& vm, JSBigInt* x, JSBigInt* y, ExtraDigitsHandling extraDigits, SymmetricOp symmetric, BitwiseOp&& op) 1032 1061 { 1033 1062 unsigned xLength = x->length(); … … 1085 1114 } 1086 1115 1087 JSBigInt* JSBigInt::absoluteAddOne(VM& vm, JSBigInt* x, bool sign)1116 JSBigInt* JSBigInt::absoluteAddOne(VM& vm, JSBigInt* x, SignOption signOption) 1088 1117 { 1089 1118 unsigned inputLength = x->length(); … … 1112 1141 ASSERT(!carry); 1113 1142 1114 result->setSign(sign );1143 result->setSign(signOption == SignOption::Signed); 1115 1144 return result->rightTrim(vm); 1116 1145 } -
trunk/Source/JavaScriptCore/runtime/JSBigInt.h
r236737 r236901 115 115 116 116 static JSBigInt* bitwiseAnd(VM&, JSBigInt* x, JSBigInt* y); 117 static JSBigInt* bitwiseOr(VM&, JSBigInt* x, JSBigInt* y); 117 118 118 119 private: … … 161 162 }; 162 163 163 static JSBigInt* absoluteBitwiseOp(VM&, JSBigInt* x, JSBigInt* y, ExtraDigitsHandling, SymmetricOp, std::function<Digit(Digit, Digit)> op); 164 template<typename BitwiseOp> 165 static JSBigInt* absoluteBitwiseOp(VM&, JSBigInt* x, JSBigInt* y, ExtraDigitsHandling, SymmetricOp, BitwiseOp&&); 166 164 167 static JSBigInt* absoluteAnd(VM&, JSBigInt* x, JSBigInt* y); 165 168 static JSBigInt* absoluteOr(VM&, JSBigInt* x, JSBigInt* y); 166 169 static JSBigInt* absoluteAndNot(VM&, JSBigInt* x, JSBigInt* y); 167 170 168 static JSBigInt* absoluteAddOne(VM&, JSBigInt* x, bool sign); 171 enum class SignOption { 172 Signed, 173 Unsigned 174 }; 175 176 static JSBigInt* absoluteAddOne(VM&, JSBigInt* x, SignOption); 169 177 static JSBigInt* absoluteSubOne(VM&, JSBigInt* x, unsigned resultLength); 170 178
Note: See TracChangeset
for help on using the changeset viewer.